天天看點

應用RecyclerView實作Gallery相冊效果——注意引入recyclerview-v7的版本

整理總結自鴻洋的部落格:http://blog.csdn.net/lmj623565791/article/details/38173061/

一、初次使用RecyclerView實作”擴充卡“的功能

1、MainActivity.java

public class MainActivity extends Activity {

    private RecyclerView mRecyclerView;
    private GalleryAdapter mAdapter;
    private List<Integer> mDatas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        //獲得資料
        initDatas();
        //得到控件
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview_horizontal);
        //設定布局管理器
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        //設定擴充卡
        mAdapter = new GalleryAdapter(this, mDatas);
        mRecyclerView.setAdapter(mAdapter);
    }

    private void initDatas() {
        mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l));
    }
}
           

2、activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview_horizontal"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_centerVertical="true"
        android:background="#FF0000"
        android:scrollbars="none" />

</RelativeLayout>
           

3、activity_index_gallery_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="120dp"
    android:layout_height="120dp"
    android:background="@drawable/item_bg02">

    <ImageView
        android:id="@+id/id_index_gallery_item_image"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="5dp"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/id_index_gallery_item_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/id_index_gallery_item_image"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="5dp"
        android:layout_marginTop="5dp"
        android:text="some info"
        android:textColor="#ff0000"
        android:textSize="12dp" />

</RelativeLayout>
           

4、GalleryAdapter.java

/**
 * Created by jiatao on 2016/06/14 18:26
 * Description: 應用RecyclerView的擴充卡
 */
public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> {

    private LayoutInflater mInflater;
    private List<Integer> mDatas;

    public GalleryAdapter(Context context, List<Integer> datats) {
        mInflater = LayoutInflater.from(context);
        mDatas = datats;
    }

    /**
     * 建立内部靜态類,必須繼承RecyclerView.ViewHolder。承上啟下。
     * 上:RecyclerView.Adapter<GalleryAdapter.ViewHolder>
     * 下:ViewHolder viewHolder = new ViewHolder(view);
     * 詳細說明:
     *      我們建立的ViewHolder必須繼承RecyclerView.ViewHolder,這個RecyclerView.ViewHolder在構造時必須傳入一個View,
     *      這個View相當于我們ListView getView中的convertView (即:把我們需要inflate的item布局傳入)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView mImg;
        TextView mTxt;

        public ViewHolder(View view) {
            super(view);
        }
    }

    /**
     * 擷取總條目數,同BaseAdapter
     */
    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    /**
     * 建立ViewHolder
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = mInflater.inflate(R.layout.activity_index_gallery_item, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(view);
        viewHolder.mImg = (ImageView) view.findViewById(R.id.id_index_gallery_item_image);
        return viewHolder;
    }

    /**
     * 将資料綁定到ViewHolder
     */
    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
        viewHolder.mImg.setImageResource(mDatas.get(i));
    }

}
           

二、為RecyclerView添加OnItemClickListener回調

1、MainActivity.java

public class MainActivity extends Activity {

    private RecyclerView mRecyclerView;
    private GalleryAdapter mAdapter;
    private List<Integer> mDatas;

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

        initDatas();//獲得資料
        initView(); //初始化視圖
    }

    private void initDatas() {
        mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l));
    }
    private void initView() {
        //得到控件
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview_horizontal);
        //設定布局管理器
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        //設定擴充卡
        mAdapter = new GalleryAdapter(this, mDatas);
        //添加點選監聽
        mAdapter.setmOnItemClickListener(new GalleryAdapter.OnItemClickListener() {
            @Override
            public void itemClick(View view, int position) {
                Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show();
            }
        });
        mRecyclerView.setAdapter(mAdapter);
    }
}
           

2、activity_main.xml

同上

3、activity_index_gallery_item.xml

同上

4、GalleryAdapter.java

/**
 * Created by jiatao on 2016/06/15 7:26
 * Description: 應用RecyclerView的擴充卡
 *  添加OnItemClickListener回調接口,實作對條目的點選事件
 */
public class GalleryAdapter extends RecyclerView.Adapter<GalleryAdapter.ViewHolder> {

    /**********************添加OnItemClickListener回調接口↓↓******************************/
    public interface OnItemClickListener{
        void itemClick(View view, int position);
    }
    private OnItemClickListener mOnItemClickListener;
    public void setmOnItemClickListener(OnItemClickListener listener){
        this.mOnItemClickListener = listener;
    }
    /**********************添加OnItemClickListener回調接口↑↑******************************/

    private LayoutInflater mInflater;
    private List<Integer> mDatas;

    public GalleryAdapter(Context context, List<Integer> datats) {
        mInflater = LayoutInflater.from(context);
        mDatas = datats;
    }

    /**
     * 建立内部靜态類,必須繼承RecyclerView.ViewHolder。承上啟下。
     * 上:RecyclerView.Adapter<GalleryAdapter.ViewHolder>
     * 下:ViewHolder viewHolder = new ViewHolder(view);
     * 詳細說明:
     *      我們建立的ViewHolder必須繼承RecyclerView.ViewHolder,這個RecyclerView.ViewHolder在構造時必須傳入一個View,
     *      這個View相當于我們ListView getView中的convertView (即:把我們需要inflate的item布局傳入)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView mImg;
        TextView mTxt;

        public ViewHolder(View view) {
            super(view);
        }
    }

    /**
     * 擷取總條目數,同BaseAdapter
     */
    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    /**
     * 建立ViewHolder
     */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = mInflater.inflate(R.layout.activity_index_gallery_item, viewGroup, false);
        ViewHolder viewHolder = new ViewHolder(view);
        viewHolder.mImg = (ImageView) view.findViewById(R.id.id_index_gallery_item_image);
        return viewHolder;
    }

    /**
     * 将資料綁定到ViewHolder
     */
    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
        viewHolder.mImg.setImageResource(mDatas.get(position));
        //如果設定了點選事件的回調
        if(mOnItemClickListener != null){
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.itemClick(viewHolder.itemView, position);
                }
            });
        }
    }

}
           

三、自定義RecyclerView實作滾動時内容關聯

1、MainActivity.java

public class MainActivity extends Activity {

    private GalleryAdapter mAdapter;
    private ImageView id_content;
    private CustomRecyclerView mCustomRecyclerView;
    private List<Integer> mDatas;

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

        initDatas();//獲得資料
        initView();//初始化視圖
    }

    private void initDatas() {
        mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l));
    }

    private void initView() {
        //得到控件
        id_content = (ImageView) findViewById(R.id.id_content);
        mCustomRecyclerView = (CustomRecyclerView) findViewById(R.id.id_recyclerview_horizontal);
        //設定布局管理器
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mCustomRecyclerView.setLayoutManager(linearLayoutManager);
        //設定擴充卡
        mAdapter = new GalleryAdapter(this, mDatas);
        //添加點選監聽
        mAdapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() {
            @Override
            public void itemClick(View v, int position) {
                Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show();
            }
        });
        mCustomRecyclerView.setAdapter(mAdapter);
        //添加滑動監聽
        mCustomRecyclerView.setOnItemScrollChangeListener(new CustomRecyclerView.OnItemScrollChangeListener() {
            @Override
            public void onChange(View view, int position) {
                 id_content.setImageResource(mDatas.get(position));
            }
        });
    }
}
           

2、activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <ImageView
            android:id="@+id/id_content"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:scaleType="centerCrop" />
    </FrameLayout>

    <com.cctvjiatao.recyclerviewgallery.view.CustomRecyclerView
        android:id="@+id/id_recyclerview_horizontal"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_gravity="bottom"
        android:background="#FF0000"
        android:scrollbars="none" />

</LinearLayout>
           

3、activity_index_gallery_item.xml

同上

4、GalleryAdapter.java

同上

5、CustomRecyclerView.java

/**
 * Created by jiatao on 2016/06/15 09:55
 * Description: 自定義RecyclerView
 */
public class CustomRecyclerView extends RecyclerView {

    private View mCurrentView;

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**********************添加OnItemScrollChangeListener回調接口相關↓↓******************************/
    //定義一個滾動時回調的接口,然後在onTouchEvent中,監聽ACTION_MOVE,使用者手指滑動時,不斷地把目前第一個View回調回去
    public interface OnItemScrollChangeListener {
        void onChange(View view, int position);
    }
    private OnItemScrollChangeListener mItemScrollChangeListener;
    public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) {
        this.mItemScrollChangeListener = listener;
    }
    /**********************添加OnItemScrollChangeListener回調接口相關↑↑******************************/

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mCurrentView = getChildAt(0);
        if (mItemScrollChangeListener != null) {
            mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView));//Android 6.0中View.getChildPosition()過時,更新為View.getChildLayoutPosition
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (e.getAction() == MotionEvent.ACTION_MOVE) {
            mCurrentView = getChildAt(0);
            // Log.e("TAG", getChildLayoutPosition(getChildAt(0)) + "");
            if (mItemScrollChangeListener != null) {
                mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView));//Android 6.0中View.getChildPosition()過時,更新為View.getChildLayoutPosition
            }
        }
        return super.onTouchEvent(e);
    }
}
           

四、優化與打造真正的Gallery效果效果—— 所用jar包是 recyclerview-v7:23.3.0

1、MainActivity.java

public class MainActivity extends Activity {

    private GalleryAdapter mAdapter;
    private ImageView id_content;
    private CustomRecyclerView mCustomRecyclerView;
    private List<Integer> mDatas;

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

        initDatas();//獲得資料
        initView();//初始化視圖
    }

    private void initDatas() {
        mDatas = new ArrayList<Integer>(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f, R.mipmap.g, R.mipmap.h, R.mipmap.l));
    }

    private void initView() {
        //得到控件
        id_content = (ImageView) findViewById(R.id.id_content);
        mCustomRecyclerView = (CustomRecyclerView) findViewById(R.id.id_recyclerview_horizontal);
        //設定布局管理器
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mCustomRecyclerView.setLayoutManager(linearLayoutManager);
        //設定擴充卡
        mAdapter = new GalleryAdapter(this, mDatas);
        //添加點選監聽
        mAdapter.setOnItemClickListener(new GalleryAdapter.OnItemClickListener() {
            @Override
            public void itemClick(View v, int position) {
//                Toast.makeText(MainActivity.this, position+"", Toast.LENGTH_SHORT).show();
                id_content.setImageResource(mDatas.get(position));
            }
        });
        mCustomRecyclerView.setAdapter(mAdapter);
        //添加滑動監聽
        mCustomRecyclerView.setOnItemScrollChangeListener(new CustomRecyclerView.OnItemScrollChangeListener() {
            @Override
            public void onChange(View view, int position) {
                 id_content.setImageResource(mDatas.get(position));
            }
        });
    }
}
           

2、activity_main.xml

同上

3、activity_index_gallery_item.xml

同上

4、GalleryAdapter.java

同上

5、CustomRecyclerView.java

/**
 * Created by jiatao on 2016/06/15 09:55
 * Description: 自定義RecyclerView,使用 recyclerview-v7-21.0.3 即以上的版本
 *  放棄重寫onTouchEvent方法,而是讓這個類實作RecyclerView.OnScrollListener接口,然後設定監聽,在onScrolled裡面進行判斷。
 *  至于優化:使用了一個成員變化存儲目前第一個View,隻有第一個View發生變化時才回調
 */
public class CustomRecyclerView extends RecyclerView {

    /**********************添加OnItemScrollChangeListener回調接口相關↓↓******************************/
    public interface OnItemScrollChangeListener {
        void onChange(View view, int position);
    }
    private OnItemScrollChangeListener mItemScrollChangeListener;
    public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) {
        this.mItemScrollChangeListener = listener;
    }
    /**********************添加OnItemScrollChangeListener回調接口相關↑↑******************************/

    private View mCurrentView;

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.addOnScrollListener(new MyScrollListener());//從 recyclerview-v7-21.0.3 開始 setOnScrollListener()過時,更新為 addOnScrollListener()
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mCurrentView = getChildAt(0);
        if (mItemScrollChangeListener != null) {
            mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView));//從 recyclerview-v7-21.0.3 開始 getChildPosition()過時,更新為 getChildLayoutPosition
        }
    }

    /**********************添加RecyclerView.OnScrollListener監聽相關↓↓******************************/
    // 從 recyclerview-v7-21.0.3 開始,RecyclerView.OnScrollListener 已不是接口,而是抽象類了,是以要用如下寫法了
    //  recyclerview-v7-21.0.3 之前的版本可以使用 public class CustomRecyclerView extends RecyclerView implements RecyclerView.OnScrollListener{……}的寫法
    private class MyScrollListener extends RecyclerView.OnScrollListener  {
        public MyScrollListener() {
            super();
        }
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            View newView = getChildAt(0);
            if(mItemScrollChangeListener != null){
                if(newView != null && newView != mCurrentView){
                    mCurrentView = newView;
                    mItemScrollChangeListener.onChange(mCurrentView, getChildLayoutPosition(mCurrentView));
                }
            }
        }
    }
    /**********************添加RecyclerView.OnScrollListener回調接口相關↑↑******************************/

}
           

五、優化與打造真正的Gallery效果效果—— 所用jar包是 recyclerview-v7:21.0.3

1、MainActivity.java

同上

2、activity_main.xml

同上

3、activity_index_gallery_item.xml

同上

4、GalleryAdapter.java

同上

5、CustomRecyclerView.java

/**
 * Created by jiatao on 2016/06/15 09:55
 * Description: 自定義RecyclerView,使用 recyclerview-v7-21.0.3 及以下的版本
 *  放棄重寫onTouchEvent方法,而是讓這個類實作RecyclerView.OnScrollListener接口,然後設定監聽,在onScrolled裡面進行判斷。
 *  至于優化:使用了一個成員變化存儲目前第一個View,隻有第一個View發生變化時才回調
 */
public class CustomRecyclerView extends RecyclerView implements RecyclerView.OnScrollListener {

    /**********************添加OnItemScrollChangeListener回調接口相關↓↓******************************/
    public interface OnItemScrollChangeListener {
        void onChange(View view, int position);
    }
    private OnItemScrollChangeListener mItemScrollChangeListener;
    public void setOnItemScrollChangeListener(OnItemScrollChangeListener listener) {
        this.mItemScrollChangeListener = listener;
    }
    /**********************添加OnItemScrollChangeListener回調接口相關↑↑******************************/

    private View mCurrentView;

    public CustomRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnScrollListener(this);//從 recyclerview-v7-21.0.3 開始 setOnScrollListener()過時,更新為 addOnScrollListener()
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mCurrentView = getChildAt(0);
        if (mItemScrollChangeListener != null) {
            mItemScrollChangeListener.onChange(mCurrentView, getChildPosition(mCurrentView));//從 recyclerview-v7-21.0.3 開始 getChildPosition()過時,更新為 getChildLayoutPosition
        }
    }

    /**********************添加RecyclerView.OnScrollListener監聽相關↓↓******************************/
    //  recyclerview-v7-21.0.3 之前的版本可以使用這種 implements RecyclerView.OnScrollListener 的寫法
    // 從 recyclerview-v7-21.0.3 開始,RecyclerView.OnScrollListener 已不是接口,而是抽象類了,就不能用以下寫法,
    @Override
    public void onScrollStateChanged(int newState) {
    }

    @Override
    public void onScrolled(int dx, int dy) {
        View newView = getChildAt(0);
        if(mItemScrollChangeListener != null){
            if(newView != null && newView != mCurrentView){
                mCurrentView = newView;
                mItemScrollChangeListener.onChange(mCurrentView, getChildPosition(mCurrentView));
            }
        }
    }
    /**********************添加RecyclerView.OnScrollListener回調接口相關↑↑******************************/

}