这个代码在网上有,
- 横向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,瀑布流等效果)。