1. 程式人生 > >複雜RecyclerView的實現(新增底部瀑布流效果)

複雜RecyclerView的實現(新增底部瀑布流效果)

言歸正傳,我們首先來看看實現的效果:


這篇文章主要講的是底部瀑布流的實現,如果對於上面的佈局存在疑問的話,請轉移我的另一篇部落格:

言歸正傳:

看到這種效果圖的第一反應便是,臥槽,這什麼鬼,佈局太複雜了。

這種反應很正常,因為木有從一個巨集觀的角度去分析問題。依據之前部落格的思路,我們根據不同的ItemType進行區分不同型別的條目,然後根據Type建立不同的ViewHolder,接著再進行setData()的資料繫結。介紹這個思路是為了告訴大家,總體的思路不變,這時候,有的同學可能會問了,江老師(某田姓同學一直這麼叫我,哈哈),這下面的條目難道是和之前橫向佈局一樣,定義一個ScrollView往裡面新增相應的條目嗎,No,Too young,Too Simple。

下面實際上是另外一個RecyclerView,那麼某田姓同學又會問了,“這裡的高度是怎麼做出來這種效果的,直接的佈局做不出來啊?”,這裡我們就要介紹一種新的佈局管理器,那就是:

StaggeredGridLayoutManager 瀑布流式佈局管理器(可以實現類似於GridView的表格效果):詳見hongyang大神的部落格:點選開啟連結

嗯,理清楚了思路之後,我們來進行相關的書寫吧:

1.首先我們需要定義底部瀑布流的Adapter:MyRecyclerViewChileAdapter

老步驟,就不必多說了:

首先,建立構造方法以及定義相關的屬性:

    //定義常用的引數
    private Context ctx;
    private ArrayList<String> arrayList;
    private List<Integer> mHeights = new ArrayList<>();

    public MyRecyclerViewChileAdapter(Context ctx, ArrayList<String> arrayList) {
        this.ctx = ctx;
        this.arrayList = arrayList;
    }

然後呢,重寫幾個重要的方法:
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder holder = null;
        holder = new ViewHolder1(View.inflate(ctx, R.layout.item4_layout, null));
        return holder;
    }

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

        ((ViewHolder1) holder).setData(position);
    }


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

這幾個方法再不會的同學就要打屁股了,哈哈。

然後,重點來了,我們的高度差是怎麼設定的呢?高度是根據返回條目中的圖片高度設定的,但是這裡由於沒有服務,所以產生的條目高度都是我隨機生成的,為了展示效果所以誇張了點兒,哈哈。

    //為每種佈局定義自己的ViewHolder
    public class ViewHolder1 extends RecyclerView.ViewHolder {
        private TextView home_read_title;
        private ImageView home_read_piv_iv;

        public ViewHolder1(View itemView) {
            super(itemView);
            if (mHeights.size() <= getItemCount()) {
                mHeights.add((int) (500 + Math.random() * 400));
            }
            home_read_title = (TextView) itemView.findViewById(R.id.home_read_title);
            home_read_piv_iv = (ImageView) itemView.findViewById(R.id.home_read_piv_iv);

            home_read_title.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }

隨機數獲取之後,我們便可以隨心所欲的設定高度啦!!!
        public void setData(int position) {
            ViewGroup.LayoutParams layoutParams = home_read_piv_iv.getLayoutParams();
            if (mHeights.size() > position)
                layoutParams.height = mHeights.get(position);
            else layoutParams.height = 589;
            home_read_piv_iv.setLayoutParams(layoutParams);
            home_read_title.setText(arrayList.get(position) + "啊哈哈哈哈哈哈");
        }

注意一下,這裡的setData()方法是在之前打的RecyclerView中的onBindViewHolder方法中呼叫的,而產生隨機高度的方法也就是構造方法是在onCreateViewHolder中呼叫的。

下面貼出來完整的Adapter的程式碼:

package com.marsjiang.complexrecyclerview.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.marsjiang.complexrecyclerview.R;

import java.util.ArrayList;
import java.util.List;

/**
 * RecyclerView的Adapter
 * Created by Jiang on 2017-07-17.
 */

public class MyRecyclerViewChileAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    //定義常用的引數
    private Context ctx;
    private ArrayList<String> arrayList;
    private List<Integer> mHeights = new ArrayList<>();

    public MyRecyclerViewChileAdapter(Context ctx, ArrayList<String> arrayList) {
        this.ctx = ctx;
        this.arrayList = arrayList;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView.ViewHolder holder = null;
        holder = new ViewHolder1(View.inflate(ctx, R.layout.item4_layout, null));
        return holder;
    }

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

        ((ViewHolder1) holder).setData(position);
    }


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


    //為每種佈局定義自己的ViewHolder
    public class ViewHolder1 extends RecyclerView.ViewHolder {
        private TextView home_read_title;
        private ImageView home_read_piv_iv;

        public ViewHolder1(View itemView) {
            super(itemView);
            if (mHeights.size() <= getItemCount()) {
                mHeights.add((int) (500 + Math.random() * 400));
            }
            home_read_title = (TextView) itemView.findViewById(R.id.home_read_title);
            home_read_piv_iv = (ImageView) itemView.findViewById(R.id.home_read_piv_iv);

            home_read_title.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }

        public void setData(int position) {
            ViewGroup.LayoutParams layoutParams = home_read_piv_iv.getLayoutParams();
            if (mHeights.size() > position)
                layoutParams.height = mHeights.get(position);
            else layoutParams.height = 589;
            home_read_piv_iv.setLayoutParams(layoutParams);
            home_read_title.setText(arrayList.get(position) + "啊哈哈哈哈哈哈");
        }
    }

}

好的接下來就是設定Adapter和設定佈局管理器的方法了,這裡參照了某個大神的寫法,不好意思了,部落格地址我沒找到:

package com.marsjiang.complexrecyclerview.widget;

import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.DisplayMetrics;

/**
 * Created by Jiang on 2017/1/9.
 * 用於改變recycleview載入更多結束以後向上滑動一段距離是,平滑, 可以控制時間
 */

public class MyStaggerGrildLayoutManger extends StaggeredGridLayoutManager {


    private float MILLISECONDS_PER_INCH = 1f;
    private Context contxt;

    public MyStaggerGrildLayoutManger(Context context, int spanCount, int orientation) {
        super(spanCount, orientation);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext()) {
                    @Override
                    public PointF computeScrollVectorForPosition(int targetPosition) {
//                        return MyStaggerGrildLayoutManger.this.computeScrollVectorForPosition(targetPosition);
                        return null;
                    }

                    //This returns the milliseconds it takes to
                    //scroll one pixel.
                    @Override
                    protected float calculateSpeedPerPixel
                    (DisplayMetrics displayMetrics) {
                        return MILLISECONDS_PER_INCH / displayMetrics.density;
                        //返回滑動一個pixel需要多少毫秒
                    }

                };
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }


    public void setSpeedSlow() {
        //自己在這裡用density去乘,希望不同解析度裝置上滑動速度相同
        //0.3f是自己估摸的一個值,可以根據不同需求自己修改
        MILLISECONDS_PER_INCH = contxt.getResources().getDisplayMetrics().density * 0.3f;
    }

    public void setSpeedFast() {
        MILLISECONDS_PER_INCH = contxt.getResources().getDisplayMetrics().density * 0.03f;
    }


}

打完,收工,跑一跑,驚喜不斷,哈哈,這樣可比之前addHeader以及addFooter實現複雜條目佈局來的方便的多了。嗯,就到這裡,有點兒困了!

技術在於分享與提升,哈哈,程式碼地址:  點選開啟連結   歡迎Star