Android-UI布局---RecyclerView学习(二)利用它做的相册集效果

2019-07-08 16:25:08 浏览数 (1)

这个代码在网上有,

  • 横向ListView的功能,参考Android 自定义RecyclerView 实现真正的Gallery效果

首先说布局文件:

RecyclerView视图中的item的布局:

代码语言:javascript复制
<?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:textColor="#ff0000"
        android:text="some info"
        android:textSize="12dp" />

</RelativeLayout>

就是一个图片一个文字

接下来是主布局:也就是效果图那页:

代码语言:javascript复制
<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"
            android:src="@drawable/ic_launcher" />
    </FrameLayout>

    <com.example.zhy_horizontalscrollview03.MyRecyclerView
        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>

这个布局下面是高度120dp 宽度填充父窗体,然后整个手机屏幕多余的空间都给了上面的imageview 视图

接下来是就是视图的自定义:com.example.zhy_horizontalscrollview03.MyRecyclerView

代码语言:javascript复制
public class MyRecyclerView extends RecyclerView implements OnScrollListener
{

	/**
	 *记录当前的第一个View
	 */
	private View mCurrentView;
	/**
	 * 滚动监听器
	 */
	private OnItemScrollChangeListener mItemScrollChangeListener;

	/**
	 * 设置监听器
	 * @param mItemScrollChangeListener
	 */
	public void setOnItemScrollChangeListener(OnItemScrollChangeListener mItemScrollChangeListener)
	{
		this.mItemScrollChangeListener = mItemScrollChangeListener;
	}

	/**
	 * 自定义了一个接口方法,用于ScrollListener 每个item 滚动的点击响应事件
	 */
	public interface OnItemScrollChangeListener
	{
		void onChange(View view, int position);
	}

	/**
	 * 继承 RecyclerView 必须要重写的方法
	 * 构造函数,在这里设置 调用 ScrollListener的滚动事件
	 */
	public MyRecyclerView(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		//implements OnScrollListener 启动
		this.setOnScrollListener(this);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b)
	{//左上角的left、top以及右下角right、bottom值
		super.onLayout(changed, l, t, r, b);
		//重载该函数,实现的功能就下面实时监听当前的子View  
		// 首先申明 这里是 水平混动
		//需要实现的效果就是每次你滑动停止之后,srcollView 第一个View 展现在上面的大图片中
		mCurrentView = getChildAt(0);

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


	/**
	 * implements OnScrollListener 必须要重载的方法
	 */
	@Override
	public void onScrollStateChanged(int arg0)
	{
	}

	/**
	 * implements OnScrollListener 必须要重载的方法
	 *滚动时,判断当前第一个View是否发生变化,发生才回调
	 */
	@Override
	public void onScrolled(int arg0, int arg1)
	{
		View newView = getChildAt(0);

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

	}

}

在使用RecyclerView的时候我们需要定义一个适配器:

代码语言:javascript复制
public class GalleryAdapter extends	RecyclerView.Adapter<GalleryAdapter.ViewHolder> {

	/**
	 *定义回调接口
	 */
	public interface OnItemClickLitener {
		void onItemClick(View view, int position);//点击事件
	}
	/**
	 * 单击 点击监听事件变量
	 */
	private OnItemClickLitener mOnItemClickLitener;

	/**
	 * 设置
	 * @param mOnItemClickLitener
	 */
	public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
		this.mOnItemClickLitener = mOnItemClickLitener;
	}

	private LayoutInflater mInflater;//布局填充器
	private List<Integer> mDatas;//适配器绑定的数据

	/**
	 * 构造函数
	 */
	public GalleryAdapter(Context context, List<Integer> datats) {
		mInflater = LayoutInflater.from(context);
		mDatas = datats;
	}

	/**
	 *ViewHolder 跟listView里面一样  属性是item 布局里面各个视图控件
	 */
	public static class ViewHolder extends RecyclerView.ViewHolder {
		public ViewHolder(View arg0) {
			//这里面可以先找到各个视图控件,
			super(arg0);
		}

		ImageView mImg;
		TextView mTxt;
	}

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

	@Override
	public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
		//找到对应的布局item
		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;
	}

	/**
	 * 该函数用来进行数据填充的,同时如果有监听事件,也在这里面
	 */
	@Override
	public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
		// 布局填充数据
		viewHolder.mImg.setImageResource(mDatas.get(i));
		// 如果设置了回调,则设置点击事件
		if (mOnItemClickLitener != null) {
			viewHolder.itemView.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					//设置点击事件 具体的调用执行,由当前的adapter实例进行操作
					mOnItemClickLitener.onItemClick(viewHolder.itemView, i);
				}
			});
		}

	}

}

可以参考下 Listview的适配器时候的写法,基本一致,只是在我们自己定义的适配器中加入了 自定义的点击事件,回调接口

接下来就是对应的activity类了:

代码语言:javascript复制
public class MainActivity extends Activity
{

	private MyRecyclerView mRecyclerView;
	private GalleryAdapter mAdapter;
	private List<Integer> mDatas;
	private ImageView mImg ; 
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);
		
		mImg = (ImageView) findViewById(R.id.id_content);

		mDatas = new ArrayList<Integer>(Arrays.asList(R.drawable.a,
				R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e,
				R.drawable.f, R.drawable.g, R.drawable.h, R.drawable.l));

		mRecyclerView = (MyRecyclerView) 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);

		//滚动布局的滑动事件监听 每次滑完展现第一个
		mRecyclerView.setOnItemScrollChangeListener(new OnItemScrollChangeListener()
		{
			@Override
			public void onChange(View view, int position)
			{
				mImg.setImageResource(mDatas.get(position));
			};
		});
		//对每一个item点击事件的处理,这里就不是展现第一个,而是点击谁就展现谁了
		mAdapter.setOnItemClickLitener(new OnItemClickLitener()
		{
			@Override
			public void onItemClick(View view, int position)
			{
				mImg.setImageResource(mDatas.get(position));
			}
		});

	}

}

整个代码就结束了,很清晰也很容易理解  。需要学习的第二个知识点就是:在对应的activity中关于RecyclerView 的使用

RecyclerView的使用代码:

代码语言:javascript复制
		//找到对应的视图控件
		mRecyclerView = (MyRecyclerView) 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);

只需要这三个关键的地方就可以了  下面是基本使用方法:

基本使用

鉴于我们对于ListView的使用特别的熟悉,对比下RecyclerView的使用代码:后面两点就看你的具体需求了

 mRecyclerView = findView(R.id.id_recyclerview); //设置布局管理器 mRecyclerView.setLayoutManager(layout); //设置adapter mRecyclerView.setAdapter(adapter) //设置Item增加、移除动画 mRecyclerView.setItemAnimator(new DefaultItemAnimator()); //添加分割线 mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL_LIST)); 

相比较于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView基本需要上面一系列的步骤,那么为什么会添加这么多的步骤呢?

那么就必须解释下RecyclerView的这个名字了,从它类名上看,RecyclerView代表的意义是,我只管Recycler View,也就是说RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。

0 人点赞