1. 程式人生 > >Fresco和 RecyclerView 實現瀑布流

Fresco和 RecyclerView 實現瀑布流

RecyclerView 實現瀑布流非常的簡單,只需要設定佈局管理為 StaggeredGridLayoutManager。然後還需要設定ItemDecorator

1:大概的步驟如下.具體的步驟在下面的下面.

0:匯入RecyclerView,Fresco

1:佈局裡面新增RecyclerView,

2:建立item的佈局,這個佈局可以使用Fresco的SimpleDrawweView,記住要在Application裡面進行初始化。

3:建立Product的實體類,這個裡面包含了四個變數,圖片地址,圖片名稱,圖片的寬度,圖片的高度。

4:建立 Adatper, PicRecyclerViewAdapter,在這個PicRecyclerViewAdapter裡面首先要建立PicViewHolder繼承RecyclerView.ViewHolder,這個ViewHolder必須要先建立,因為下面繼承RecyclerView.Adapter裡面要用到
5:讓我們的adpter,PicRecyclerViewAdapter繼承RecyclerView.Adatper, extends RecyclerView.Adapter<PicRecyclerViewAdapter.PicViewHolder>
繼承裡面的方法,包括onCreateViewHolder,和onBindViewHolder。

public PicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View ret = LayoutInflater.from(context).inflate(R.layout.item_recyclerview,parent,false);
        return new PicViewHolder(ret);
    }

//瀑布流裡面,我們會從伺服器得到寬度和高度,然後通過這個設定寬高比。
    @Override
    public void onBindViewHolder(PicViewHolder holder, int position) {
        Product product = list.get(position);
        holder.pic.setImageURI(Uri.parse(product.getLocalPosition()));
        holder.textView.setText(product.getProductName());
    }

6:建立每一個Item之間的間隔 通過建立一個繼承了ItemDecorator的類來做,裡面有getItemOffSet方法。來設定上下左右的距離

7:通過程式碼設定佈局管理和adapter,以及一些模擬資料。
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        //新增間隔,Decorator 的翻譯就是裝飾師,粉刷匠
        MyItemDecorator myItemDecorator = new MyItemDecorator(10);
        mRecyclerView.addItemDecoration(myItemDecorator);
        mRecyclerView.setAdapter(adapter);

2:具體的步驟:

0:匯入RecyclerView,Fresco

1:佈局裡面新增RecyclerView,

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android
:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/recyclerview"></android.support.v7.widget.RecyclerView> </RelativeLayout>
2:建立item的佈局,這個佈局可以使用Fresco的SimpleDrawweView,記住要在Application裡面進行初始化。

千萬記住了SimpleDraweeView不能是全部的wrap_content

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent">
<com.facebook.drawee.view.SimpleDraweeView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/item_simpleDraweeView"
app:placeholderImage="@mipmap/ic_launcher"/>
    <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/item_name"/>
</LinearLayout>
建立MyApplication
package tech.androidstudio.recyclerviewdemo;

import android.app.Application;

import com.facebook.drawee.backends.pipeline.Fresco;

/**
 * Created by Kodulf on 2016/3/15.
 */
public class MyApplication extends Application {
    @Override
public void onCreate() {
        super.onCreate();
        Fresco.initialize(this);
    }
}

在清單檔案中修改:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:name=".MyApplication">

3:建立Product的實體類,這個裡面包含了四個變數,圖片地址,圖片名稱,圖片的寬度,圖片的高度。

package tech.androidstudio.recyclerviewdemo;

/**
 * Created by Kodulf on 2016/3/15.
 */
public class Product {
    private String localPosition;
    private String productName;
    private int width;
    private int height;

    public Product(String localPosition, String productName, int width, int height) {
        this.localPosition = localPosition;
        this.productName = productName;
        this.width = width;
        this.height = height;
    }

    public int getWidth() {

        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public Product(String localPosition, String productName) {
        this.localPosition = localPosition;
        this.productName = productName;
    }

    public Product() {
    }

    public String getLocalPosition() {

        return localPosition;
    }

    public void setLocalPosition(String localPosition) {
        this.localPosition = localPosition;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }
}

4:建立 Adatper, PicRecyclerViewAdapter,在這個PicRecyclerViewAdapter裡面首先要建立PicViewHolder繼承RecyclerView.ViewHolder,這個ViewHolder必須要先建立,因為下面繼承RecyclerView.Adapter裡面要用到
//必須 首先寫這個 ViewHolder,因為只有這樣才能寫裡面的引數,
// 然後才是寫繼承的 extends RecyclerView.Adapter<PicViewHolder>
public class PicViewHolder extends RecyclerView.ViewHolder{

            SimpleDraweeView pic;
            TextView textView;

        public PicViewHolder(View itemView) {
            super(itemView);
            pic=(SimpleDraweeView)itemView.findViewById(R.id.item_simpleDraweeView);
//            pic.setAspectRatio(0.9f);
pic.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.FIT_XY);
            textView=(TextView)itemView.findViewById(R.id.item_name);
        }

    }
5:讓我們的adpter,PicRecyclerViewAdapter繼承RecyclerView.Adatper, extends RecyclerView.Adapter<PicRecyclerViewAdapter.PicViewHolder>
繼承裡面的方法,包括onCreateViewHolder,和onBindViewHolder。

public PicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View ret = LayoutInflater.from(context).inflate(R.layout.item_recyclerview,parent,false);
        return new PicViewHolder(ret);
    }

//瀑布流裡面,我們會從伺服器得到寬度和高度,然後通過這個設定寬高比。
    @Override
    public void onBindViewHolder(PicViewHolder holder, int position) {
        Product product = list.get(position);
        holder.pic.setImageURI(Uri.parse(product.getLocalPosition()));
        holder.textView.setText(product.getProductName());
    }
package tech.androidstudio.recyclerviewdemo.adapter;
import android.content.Context;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.facebook.drawee.drawable.ScalingUtils;
import com.facebook.drawee.view.SimpleDraweeView;

import java.util.Collection;
import java.util.List;

import tech.androidstudio.recyclerviewdemo.Product;
import tech.androidstudio.recyclerviewdemo.R;

/**
 * Created by Kodulf on 2016/3/15.
 */
//注意 這裡 整合的 RecyclerView.Adapter
public class PicRecyclerViewAdapter extends RecyclerView.Adapter<PicRecyclerViewAdapter.PicViewHolder> {
    List<Product> list;
    Context context;
    public PicRecyclerViewAdapter(List<Product> list,Context context) {
        this.list = list;
        this.context=context;
    }

    @Override
public PicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View ret = LayoutInflater.from(context).inflate(R.layout.item_recyclerview,parent,false);
        return new PicViewHolder(ret);

        //TODO 下面的 返回方法是錯誤的,如果這樣做的話,會報錯
//TODO java.lang.NullPointerException: Attempt to invoke virtual method 'void com.facebook.drawee.view.SimpleDraweeView.setImageURI(android.net.Uri)' on a null object reference
//PicViewHolder picViewHolder = new PicViewHolder(parent);
        //return picViewHolder;
        //return null;
}

    @Override
public void onBindViewHolder(PicViewHolder holder, int position) {
        Log.d("Kodulf", "position" + position + " Uri:");
        Product product = list.get(position);
        //獲取圖片的寬高資訊,然後得到寬高比 ,然後通過FrescoSimpleDraweeViewsetAspectRatio來設定
float ratio = (float)product.getWidth() / (float)product.getHeight();
        holder.pic.setAspectRatio(ratio);
        holder.pic.setImageURI(Uri.parse(product.getLocalPosition()));

        Log.d("Kodulf", "Width=" + product.getWidth());
        Log.d("Kodulf", "Height=" +product.getHeight());
        Log.d("Kodulf","Ratio="+ratio);
        holder.textView.setText(product.getProductName());
    }

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

    //以後新增更新資料的時候會用到addAll的方法
public void addAll(Collection<? extends Product> collection){

        int size = list.size();
        list.addAll(collection);
        notifyItemRangeChanged(size, collection.size());
    }


    //必須 首先寫這個 ViewHolder,因為只有這樣才能寫裡面的引數,
// 然後才是寫繼承的 extends RecyclerView.Adapter<PicViewHolder>
public class PicViewHolder extends RecyclerView.ViewHolder{

            SimpleDraweeView pic;
            TextView textView;

        public PicViewHolder(View itemView) {
            super(itemView);
            pic=(SimpleDraweeView)itemView.findViewById(R.id.item_simpleDraweeView);
//            pic.setAspectRatio(0.9f);
pic.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.FIT_XY);
            textView=(TextView)itemView.findViewById(R.id.item_name);
        }

    }
}




6:建立每一個Item之間的間隔 通過建立一個繼承了ItemDecorator的類來做,裡面有getItemOffSet方法。來設定上下左右的距離
package tech.androidstudio.recyclerviewdemo;

import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created by Kodulf on 2016/3/15.
 */
//Decorator 的翻譯就是裝飾師,粉刷匠
public class MyItemDecorator extends RecyclerView.ItemDecoration {
    private int space;

    public MyItemDecorator(int space) {
        this.space = space;
    }

    //自定義item之間的距離,如果是第一個的話就沒有距離,
//設定上下左右的距離
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//        super.getItemOffsets(outRect, view, parent, state);
outRect.bottom=space;
        outRect.right=space;
        outRect.left=space;
        if(parent.getChildPosition(view)!=0){
            outRect.top=space;
        }
    }
}



7:通過程式碼設定佈局管理和adapter,以及一些模擬資料。
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        //新增間隔,Decorator 的翻譯就是裝飾師,粉刷匠
        MyItemDecorator myItemDecorator = new MyItemDecorator(10);
        mRecyclerView.addItemDecoration(myItemDecorator);
        mRecyclerView.setAdapter(adapter);

package tech.androidstudio.recyclerviewdemo;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;

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

import tech.androidstudio.recyclerviewdemo.adapter.PicRecyclerViewAdapter;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

/**
        List<String> listUrl = new ArrayList<String>();
        listUrl.add("http://fdfs.xmcdn.com/group16/M08/F1/13/wKgDbFal40bR7Uc6AAH3JpWhLiQ015_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group10/M07/F0/14/wKgDaVal9ZLTP5q1AAFIJeYaktQ092_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group12/M07/E8/35/wKgDXFacqEfReClFAAFvbZHe_mU331_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group9/M05/EE/15/wKgDZlagtF_yH9YXAAEyq6YSxDo657_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group11/M07/FC/B4/wKgDbValyzzy0fBpAAMdsEAuI-Q295_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group9/M01/EF/02/wKgDZlaiCqbTzvIzAAH_l7MCT-k503_android_large.jpg");
        listUrl.add("http://fdfs.xmcdn.com/group9/M01/EF/02/wKgDZlaiCqbTzvIzAAH_l7MCT-k503_android_large.jpg");
        List<Product> mList = new ArrayList<Product>();
        for(int i=0;i<7;i++){
            Product product = new Product();
//            product.setLocalPosition("res://mipmap/"+i+".png");
            product.setLocalPosition(listUrl.get(i));
            product.setProductName("Picture "+i);
            mList.add(product);
        }
*/
        //模擬資料,這裡需要獲取圖片的寬高 ,一般的在我們從伺服器請求資料的 時候 它會返回圖片的 寬高資訊
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.p1);
        Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.mipmap.p2);
        Bitmap bitmap3 = BitmapFactory.decodeResource(getResources(), R.mipmap.p3);
        Bitmap bitmap4 = BitmapFactory.decodeResource(getResources(), R.mipmap.p4);
        Bitmap bitmap5 = BitmapFactory.decodeResource(getResources(), R.mipmap.p5);
        Bitmap bitmap6 = BitmapFactory.decodeResource(getResources(), R.mipmap.p6);
        Bitmap bitmap7 = BitmapFactory.decodeResource(getResources(), R.mipmap.p7);

        List<Product> mList = new ArrayList<Product>();
        Product product1 = new Product("res://mipmap/"+R.mipmap.p1,"Picture 1",bitmap1.getWidth(),bitmap1.getHeight());
        Product product2 = new Product("res://mipmap/"+R.mipmap.p2,"Picture 2",bitmap2.getWidth(),bitmap2.getHeight());
        Product product3 = new Product("res://mipmap/"+R.mipmap.p3,"Picture 3",bitmap3.getWidth(),bitmap3.getHeight());
        Product product4 = new Product("res://mipmap/"+R.mipmap.p4,"Picture 4",bitmap4.getWidth(),bitmap4.getHeight());
        Product product5 = new Product("res://mipmap/"+R.mipmap.p5,"Picture 5",bitmap5.getWidth(),bitmap5.getHeight());
        Product product6 = new Product("res://mipmap/"+R.mipmap.p6,"Picture 6",bitmap6.getWidth(),bitmap6.getHeight());
        Product product7 = new Product("res://mipmap/"+R.mipmap.p7,"Picture 7",bitmap7.getWidth(),bitmap7.getHeight());
        mList.add(product1);
        mList.add(product2);
        mList.add(product3);
        mList.add(product4);
        mList.add(product5);
        mList.add(product6);
        mList.add(product7);


        mRecyclerView = (RecyclerView)findViewById(R.id.recyclerview);
        PicRecyclerViewAdapter adapter = new PicRecyclerViewAdapter(mList,this);
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        //新增間隔,Decorator 的翻譯就是裝飾師,粉刷匠
MyItemDecorator myItemDecorator = new MyItemDecorator(10);
        mRecyclerView.addItemDecoration(myItemDecorator);

        mRecyclerView.setAdapter(adapter);
    }
}


7:通過程式碼設定佈局管理和adapter,以及一些模擬資料。
        mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
        //新增間隔,Decorator 的翻譯就是裝飾師,粉刷匠
        MyItemDecorator myItemDecorator = new MyItemDecorator(10);
        mRecyclerView.addItemDecoration(myItemDecorator);
        mRecyclerView.setAdapter(adapter);