anewdroid / ScalableGridRecycler

7 stars 0 forks source link

How to animate from 2 columns to 1? #1

Open bahacan19 opened 8 years ago

bahacan19 commented 8 years ago

I am using a recyclerview right now. when i fully copy and implement your code in my project working well but how can i animate my 2 column recyclerview to 1 column? And also 1column -> 2 column again. Thanks

anewdroid commented 8 years ago

Hello!This was just a possible sample for a SO question.You could just modify the grid size and and change the spansize lookup to return 1 or 2 based on a setting

bahacan19 commented 8 years ago

Thanks for your reply. There is one more problem that i dont know how to deal with it. When recyclerview inflated, for 5 seconds or more no data is showing (even gridAdap.addData(imageUriList); called ). After that images are coming with animation as it's supposed to be. How can I prevent this startup delay? Thanks

anewdroid commented 8 years ago

You could be adding a lot of data which involves an initital layout calculations.Although you can batch them and reduce your load time. How many items are you adding?and how complex is your layout?

bahacan19 commented 8 years ago

40 items on start. My item layout is

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="76dp"
    android:layout_height="59dp"
    android:background="#fff"
    android:orientation="vertical"
    android:padding="3dp"
    tools:ignore="MissingPrefix">

    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/image"
        android:scaleType="centerCrop"
        android:layout_width="70dp"
        android:layout_height="53dp"/>

    <View
        android:layout_width="70dp"
        android:layout_height="53dp"
        android:background="@drawable/list_hotel_hover" />

    <TextView
        android:id="@+id/stars"
        fontPath="fonts/FontAwesome.ttf"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:textColor="#FFB800" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:layout_margin="3dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            fontPath="fonts/Roboto-Regular.ttf"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="#ffffff" />

        <TextView
            android:id="@+id/price"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dp"
            android:textColor="#ffffff" />
    </LinearLayout>
</FrameLayout>
anewdroid commented 8 years ago

your adapter initialization code too

bahacan19 commented 8 years ago

Adapter

public class HotelListAdapter extends RecyclerView.Adapter<HotelListAdapter.ViewHolder> {

    public static final int totalSpan = 100;
    private int currentSpan;
    private int spanConstant = 40;
    private int multiplier = 1;
    private GridRecyclerView grv;

    private List<Result> mDataset;
    private String nightPlaceHolder;
    private String fromPlaceHolder;
    private GridLayoutManager.SpanSizeLookup scalableSpanSizeLookUp = new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            return getCurrentSpan();
        }
    };

    public HotelListAdapter(List<Result> myDataset, GridRecyclerView GV) {
        super();
        mDataset = myDataset;
        this.grv = GV;
        currentSpan = spanConstant;
    }

    public List<Result> getmDataset() {
        return mDataset;
    }

    public void updateDataSet(List<Result> mDataset) {
        this.mDataset = mDataset;
        notifyDataSetChanged();
    }

    @Override
    public HotelListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.hotel_result_item, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(HotelListAdapter.ViewHolder holder, int position) {

        Result r = mDataset.get(position);
        Picasso.with(holder.mImage.getContext()).load(r.getPhotoUrl())
                .placeholder(R.drawable.hotel_listing_placeholder)
                .transform(new RoundedTransformation(holder.mImage.getContext().getResources().getDimensionPixelSize(R.dimen._2sdp), 0))
                .resizeDimen(R.dimen._70sdp, R.dimen._53sdp)
                .centerCrop()
                .into(holder.mImage);
        int raiting = r.getHotelClass();
        String s = "";
        for (int i = 0; i < raiting; i++) {
            s = s + "\uF005";//dolu yıldız
        }
        holder.stars.setText(s);
        holder.stars.setPadding(0, 5, 0, 0);
        holder.title.setText(r.getName());
        if (r.getProducts().size() > 0) {
            String price = String.valueOf(r.getProducts().get(0).getPrice());
            String productCurrency = r.getProducts().get(0).getCurrency();
            if (nightPlaceHolder == null)
                nightPlaceHolder = holder.price.getContext().getResources().getString(R.string.night);
            if (fromPlaceHolder == null)
                fromPlaceHolder = holder.price.getContext().getResources().getString(R.string.from);

            String formatted = OCApplication.formatTextWithCurrencyCode(productCurrency, price);
            String fullText = fromPlaceHolder + formatted + nightPlaceHolder;
            SpannableStringBuilder sBuilder = new SpannableStringBuilder(fullText);
            sBuilder.setSpan(ViewUtils.getLightSpan(holder.price.getContext()), 0, fromPlaceHolder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            sBuilder.setSpan(ViewUtils.getBoldSpan(holder.price.getContext()), fromPlaceHolder.length(), fromPlaceHolder.length() + formatted.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            sBuilder.setSpan(ViewUtils.getLightSpan(holder.price.getContext()), fromPlaceHolder.length() + formatted.length(), fullText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            holder.price.setText(sBuilder, TextView.BufferType.SPANNABLE);
            holder.price.setVisibility(View.VISIBLE);
        } else {
            holder.price.setVisibility(View.GONE);
        }
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    public Result getItem(int pos) {
        return mDataset.get(pos);
    }

    public void animate(int position) {
        setCurrentSpan(this.currentSpan==80 ?40 :80);
        delayedNotify(position, calculateRange());
    }

    public GridLayoutManager.SpanSizeLookup getScalableSpanSizeLookUp() {
        return scalableSpanSizeLookUp;
    }

    public int calculateRange() {
        int start = ((GridLayoutManager) grv.getLayoutManager()).findFirstVisibleItemPosition();
        int end = ((GridLayoutManager) grv.getLayoutManager()).findLastVisibleItemPosition();
        if (start < 0)
            start = 0;
        if (end < 0)
            end = 0;
        return end - start;
    }

    public int getCurrentSpan() {
        return currentSpan;
    }

    public void setCurrentSpan(int span) {
        this.currentSpan = span;

    }

    public void delayedNotify(final int pos, final int range) {
        grv.postDelayed(new Runnable() {
            @Override
            public void run() {
                notifyItemRangeChanged(pos - range > 0 ? pos - range : 0, range * 2 < getItemCount() ? range * 2 : range);
            }
        }, 100);
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ImageView mImage;
        public TextView stars;
        public TextView title;
        public TextView price;

        public ViewHolder(View v) {
            super(v);
            mImage = (ImageView) v.findViewById(R.id.image);
            stars = (TextView) v.findViewById(R.id.stars);
            title = (TextView) v.findViewById(R.id.title);
            price = (TextView) v.findViewById(R.id.price);
        }

    }
}

Init

 adapter = new HotelListAdapter(hotelsResponse.results, hotelsRecyclerView);
 hotelsRecyclerView.setLayoutManager(layoutManager);
 layoutManager.setSpanSizeLookup(adapter.getScalableSpanSizeLookUp());
 hotelsRecyclerView.setAdapter(adapter);
 hotelsRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this, (view, position) -> {

           adapter.animate(position);

        }));
anewdroid commented 8 years ago

can you check if your fps is stable on scroll? using the gpu overdraw function

bahacan19 commented 8 years ago

Actually this bug appears in your project too. Gallery images comes up too late.

anewdroid commented 8 years ago

Are the place holders placed?Can it just be the image decoding is taking time?

anewdroid commented 8 years ago

Sorry i'm slightly busy right now.I'll look into the code this weekend if thats fine