1. 程式人生 > >AndroidL-RecyclerView應用之實現Gallery畫廊

AndroidL-RecyclerView應用之實現Gallery畫廊

既然RecyclerView能夠實現我們夢寐以求的橫向ListView效果,那麼我們也應該可以使用RecyclerView實現複雜的Gallery效果吧?

答案顯然是可以的。眾所周知自從Gallery有眾多問題被Google遺棄後,通常實現Gallery效果的方法都是viewpager+Fragment,這樣實現起來程式碼多不說,也有不少問題需要各種設定來解決,對於新手來說,可能不是很容易理解。

今天我給大家講解下簡單的RecyclerView實現gallery效果,我這裡只講解如何監聽RecyclerView的滾動和點選事件,都是用介面形式來實現監聽。至於Fragment左右切換這部分我就不詳細說,demo也不會放上這部分的內容。

好,我們先來看看效果圖:

效果圖

要實現Gallery畫廊效果,首先得對RecyclerView增加Scroll監聽,自定義一個Recyclerview繼承系統的Recyclerview,程式碼如下:

package com.hjhrq1991.gallery;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MyRecyclerView extends RecyclerView {
	/**
	 * 當前螢幕第一個item
	 */
	private View mCurrentView;
	/**
	 * 滾動事件監聽介面
	 */
	private OnItemScrollChangeListener mItemScrollChangeListener;

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

	public void setOnItemScrollChangeListener(
			OnItemScrollChangeListener mItemScrollChangeListener) {
		this.mItemScrollChangeListener = mItemScrollChangeListener;
	}

	/**
	 * 滾動事件監聽介面
	 */
	public interface OnItemScrollChangeListener {
		void onChange(View view, int position);
	}

	/**
	 * 監聽layout的上下左右變化
	 */
	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);

		// 據我所知,不在螢幕範圍內的item會被回收掉重用,螢幕當前顯示的第一個item即為childAt(0)
		mCurrentView = getChildAt(0);

		if (mItemScrollChangeListener != null) {
			mItemScrollChangeListener.onChange(mCurrentView,
					getChildPosition(mCurrentView));
		}
	}

	/**
	 * 觸控事件監聽,小編不才,對TouchEvent事件分發這塊還不是很熟悉,所以這裡雖然寫了,但是沒有觸發onTouchEvent。
	 * 望某位大大修改了告知我一聲
	 */
	@Override
	public boolean onTouchEvent(MotionEvent e) {

		if (e.getAction() == MotionEvent.ACTION_MOVE) {
			mCurrentView = getChildAt(0);
			// Log.e("TAG", getChildPosition(getChildAt(0)) + "");
			if (mItemScrollChangeListener != null) {
				mItemScrollChangeListener.onChange(mCurrentView,
						getChildPosition(mCurrentView));

			}
		}

		return super.onTouchEvent(e);
	}

}
主要監聽左右滾動時item的變化,當上一個item0滑出螢幕時,系統就會回收排到最後,而剛才為item1的item,因為前面沒有item,成為item。因此我們在這裡通過getChildAt(0)來得到當前第一個item。
item變化示意圖

寫完介面我們就可以再layout裡使用自定義的RecyclerView,那麼問題來了,要怎麼使用這個介面呢?如果滾動到最後一個item,當前螢幕有多個item,只能取到item0,那麼其他幾個item怎麼得到呢?

這時候我們就需要給RecyclerView新增點選事件,在上一篇blog我提到我會使用介面來實現onItemClick事件。由於Adapter裡其他部分都一樣,我就不擺那麼多程式碼,詳情請看我上一篇blog的Adapter實現:

 /**
     * item點選事件的實現
     */
    class OnItemClick implements View.OnClickListener {
        private ViewHolder viewHolder;
        private int position;

        public OnItemClick(ViewHolder viewHolder,int position) {
            this.viewHolder = viewHolder;
            this.position = position;
        }

        @Override
        public void onClick(View v) {
            mOnItemClickLitener.onItemClick(viewHolder.itemView, position);
        }
    }

    /**
     * 寫一個onitemclick的介面,並在activity實現這個介面,通過此介面實現事件的回撥
     */
    public interface OnItemClickLitener
    {
        void onItemClick(View view, int position);
    }

    private OnItemClickLitener mOnItemClickLitener;

    public void setOnItemClickLitener(OnItemClickLitener onItemClickLitener)
    {
        this.mOnItemClickLitener = onItemClickLitener;
    }

在adapter當中寫一個onItemClickListener介面,和onItemScrollChangeListener一樣,都實現介面的資料回撥,取得當前item所在list的position。

並在Activity實現onitemClick事件和onItemScrollChangeListener事件。

package com.hjhrq1991.gallery;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;

import com.hjhrq1991.adapter.TestAdaper;
import com.hjhrq1991.adapter.TestAdaper.OnItemClickLitener;
import com.hjhrq1991.bean.TestInfo;
import com.hjhrq1991.gallery.MyRecyclerView.OnItemScrollChangeListener;

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

public class MainActivity extends Activity implements View.OnClickListener,
		OnItemScrollChangeListener, OnItemClickLitener {

	private int TASK_TEXT = 0;
	private int TASK_DRAWABLE = 1;
	private int TASK_CHEXKBOX = 2;

	private MyRecyclerView mrecylerView;
	private Button mAddBtn;
	private TextView mTxt;

	private TestAdaper mAdapter;

	private List<TestInfo> mList = new ArrayList<TestInfo>();

	private int[] drawable = { R.drawable.icon00, R.drawable.icon01,
			R.drawable.icon02, R.drawable.icon03, R.drawable.icon04,
			R.drawable.icon05, R.drawable.icon06, R.drawable.icon07,
			R.drawable.icon08 };

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

	private void init() {
		mrecylerView = (MyRecyclerView) findViewById(R.id.rvlist);
		mAddBtn = (Button) findViewById(R.id.add);
		mTxt = (TextView) findViewById(R.id.content);
		mAddBtn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		TestInfo info = new TestInfo(TASK_TEXT, "這是純文字");
		mAdapter.addToList(info, 3);
	}

	/**
	 * 設定資料來源
	 */
	private void getParams() {
		for (int i = 0; i < 20; i++) {
			Random mRandom = new Random();
			int n = mRandom.nextInt(8);
			TestInfo info1 = new TestInfo(TASK_TEXT, "這是純文字" + i);
			TestInfo info2 = new TestInfo(TASK_DRAWABLE, drawable[n], "這是圖片"
					+ i);
			TestInfo info3 = new TestInfo(TASK_CHEXKBOX, drawable[n], "這是複選框"
					+ i, "打鉤" + i);

			mList.add(info1);
			mList.add(info2);
			mList.add(info3);
		}
	}

	private void showDate() {
		// 建立一個線性佈局管理器
		LinearLayoutManager layoutManager = new LinearLayoutManager(this);
		layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
		// 設定
		mrecylerView.getRecycledViewPool().setMaxRecycledViews(0, 3);
		// 設定佈局管理器
		mrecylerView.setLayoutManager(layoutManager);
		// 建立Adapter,並指定資料集
		mAdapter = new TestAdaper(this, mList);
		// 設定Adapter
		mrecylerView.setAdapter(mAdapter);
		// 設定預設動畫
		mrecylerView.setItemAnimator(new DefaultItemAnimator());

		// 個人喜歡程式碼整潔點,因此喜歡實現這個介面,傳遞當前物件過去,而不喜歡通過new一個介面來實現
		mrecylerView.setOnItemScrollChangeListener(this);
		mAdapter.setOnItemClickLitener(this);

	}

	/**
	 * item點選事件
	 */
	@Override
	public void onItemClick(View view, int position) {
		// TODO Auto-generated method stub
		mTxt.setText(mList.get(position).getContent());
	}

	/**
	 * item滑動事件
	 */
	@Override
	public void onChange(View view, int position) {
		// TODO Auto-generated method stub
		mTxt.setText(mList.get(position).getContent());
	}

}

寫到這裡,基本上Gallery畫廊效果出來了,手指滾動listview或者點選item都可以引來上面的textview的變化。如果我們把textview更改為fragment,加上fragment的左右切換,就可以實現一個完整的Gallery了。不過這一步我就不做了,留給大家去嘗試。另外這個demo裡有個地方寫的不是很好,如果我還沒修改而你又改好了,希望您和我說下,我修改下給各位童鞋們學習。

附上demo下載地址:

如有轉載,請註明出處:http://blog.csdn.net/hjhrq1991