</pre> 最近在需求中遇到实现图片的滚动的效果,之前使用Gallry 这个控件就可以实现,但是在Gallry 这个控件在anroid中被舍弃掉了,因为它比较耗内存的原因,后来很多中解决方案的出现去解决图片滚动的效果比如用ScrollView 还有用viewPager 这种控件,但是自身都存在着很多缺陷,后来出现了RecyclerView 这个控件,替代了<span style="font-size:18px">Gallry 。</span><p></p><p><span style="font-size:18px"><span style="font-size:18px"></span></span></p><p><span style="font-size:18px"><span style="font-size:18px">具体使用方法:</span></span></p><p><span style="font-size:18px"><span style="font-size:18px">1 在代码中会经常这么写;</span></span></p><p><span style="font-size:18px"><span style="font-size:18px"></span></span></p><p><span style="font-size:18px"><span style="font-size:18px"></span></span></p><pre name="code" class="java">LinearLayoutManager NearbySitesLayoutManager = new LinearLayoutManager(mFragment.getActivity());
NearbySitesLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mNearBySitesRecyclerView.setLayoutManager(NearbySitesLayoutManager);
mNearBySitesRecyclerView.setHasFixedSize(true);
mNearbySitesImageAdapter = new NearbyImageAdapter(mFragment.getActivity(), mDetailCacheBean.scenicList);
mNearBySitesRecyclerView.setAdapter(mNearbySitesImageAdapter);
</pre><pre name="code" class="java">
(1)首先我们在创建LayoutManager,对于RecyclerView 这个控件 常见用到的LayoutManager 有:
-
LinearLayoutManager
-
GridLayoutManager
-
StaggeredGridLayoutManager
(2)
NearbySitesLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL)
是设置滚动方向的
(3)
mNearBySitesRecyclerView.setHasFixedSize(true);
是固定滚动的item 高度,最好设置下
(4)
mNearbySitesImageAdapter = new NearbyImageAdapter(mFragment.getActivity(), mDetailCacheBean.scenicList);
mNearBySitesRecyclerView.setAdapter(mNearbySitesImageAdapter);
设置adapter 这个和Gallery 有些类似
其次是adapter 的创建,和之前adapter 创建有些区别,
public class NearbyImageAdapter extends RecyclerView.Adapter<NearbyImageAdapter.ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {....
// 这里是创建view 的地方,和常规的adaper 的getView 类似,这里还可以设置设置view 的尺寸等
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
// 这个接口是现实显示数据的地方
}
public static class ViewHolder extends RecyclerView.ViewHolder {
// 这里是创建ViewHolder的地方 和常规的Adaper 类似
}
@Override
public int getItemCount() {
// item 的个数,类似常规的getCount()
}
其实在adapter 的使用上,和常用的adapter 有些类似,只是表现的形式有点不一样。
再次,其次在 RecyclerView 的控制如何控制每个item 之间的距离时,网上有很多的说法,其中最常见的一种方法,就是继承ItemDecoration 这个类,常见的写法是
public class SpaceItemDecoration extends RecyclerView.ItemDecoration{
private int space;
public SpaceItemDecoration(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if(parent.getChildPosition(view) != 0)
outRect.top = space;
}
}
这种方式去控制item 的空隙,最后用
addItemDecoration()这种方法设置间距,其实在项目中,我发现一种相对比较简单的方式,比如要是设置在每个item第一张图片的左边没有
间距,同时最后一张图片的右边没有
间距,同时每个item 的之间的
间距为20dp 我想这是常见的滚动需求。我的实现方式如下:
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout...., parent, false);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
params.rightMargin = 20dp;
view.setLayoutParams(params);
ViewHolder vh = new ViewHolder(view);
return vh;
}
// 在这个方法,首先给个每个item 创建的时候,设置20dp 的空隙,
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
if (DataList.size() > 0 && position == DataList.size() - 1) {
params.rightMargin = 0;
} else {
params.rightMargin = 20dp
}
}
去根据 position 设置 右间距 这是一种控制每个item 间距的一中处理方式。
再次,就是针对每个item 设置点击事件,因为RecyclerView 没有itemOnClick 事件,我们一般会在item 的OnClick 事件中去回调自定义点击接口:
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(v, .);
}
}
});
通过这种方式去实现点击的回调。
(5) 在使用RecycleView 如果每个item 的宽高的高度不一致,有的时候,会出现高度不一样,解决方案如下:
mMutexRecyclerLayout = (RecyclerView) view.findViewById(R.id.mutex_recycler_layout); MyLayoutManager recyclerLayoutManager = new MyLayoutManager(mContext);
重写recyclerLayoutManager 代码如下:
class MyLayoutManager extends LinearLayoutManager { public MyLayoutManager(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { int childCount = getItemCount(); int maxHigh = 0; for (int i = 0; i < childCount; i++) { View view = recycler.getViewForPosition(i); if (view != null) { measureChild(view, widthSpec, heightSpec); int measuredHeight = view.getMeasuredHeight(); maxHigh = maxHigh >= measuredHeight ? maxHigh : measuredHeight; } } if (maxHigh == 0) { super.onMeasure(recycler, state, widthSpec, heightSpec); } else { setMeasuredDimension(View.MeasureSpec.getSize(widthSpec), maxHigh); } } }
在onMeasure 的时候,根据测量实际的高度 动态的分配测量的高度
(6)
在item 中默认之间是没有设置间隙的,解决这个问题的之前 的方案是:
// 在这个方法,首先给个每个item 创建的时候,设置20dp 的空隙,
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
if (DataList.size() > 0 && position == DataList.size() - 1) {
params.rightMargin = 0;
} else {
params.rightMargin = 20dp
}
}
现在的结局方案是:
mRecyclerView = (RecyclerView) mGiftChoiceLayout.findViewById(R.id.gifts_givers_recyclerview); mGifsGiverChoiceAdapter = new GifsGiverChoiceAdapter(this, mHotelGiftsChoiceModelList); mRecyclerView.setAdapter(mGifsGiverChoiceAdapter); LinearLayoutManager recyclerLayoutManager = new LinearLayoutManager(this); recyclerLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); RecyclerViewItemDecoration itemDecoration = new RecyclerViewItemDecoration(LinearLayoutManager.HORIZONTAL); itemDecoration.setColor(Color.WHITE); itemDecoration.setSize(DeviceInfoUtil.getPixelFromDip(10)); mRecyclerView.addItemDecoration(itemDecoration);
自定义itemDecoration 实现 item 之间的空隙: 代码如下
package ctrip.android.hotel.order.librichtexteditor.viewholders; import android.graphics.Canvas; import android.graphics.Paint; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; /** * Created by bkhu on 16/11/22. */ public class RecyclerViewItemDecoration extends RecyclerView.ItemDecoration { /** * 水平方向 */ public static final int HORIZONTAL = LinearLayoutManager.HORIZONTAL; /** * 垂直方向 */ public static final int VERTICAL = LinearLayoutManager.VERTICAL; private Paint mPaint; private int mSize; private int mOrientation; public RecyclerViewItemDecoration(int orientation) { this.mOrientation = orientation; mPaint = new Paint(); } public void setSize(int size) { this.mSize = size; } public void setColor(int color) { mPaint.setColor(color); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); if (mOrientation == HORIZONTAL) { drawVertical(c, parent); } else if (mOrientation == VERTICAL) { drawHorizontal(c, parent); } } private void drawVertical(Canvas canvas, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); int childCount = parent.getChildCount(); int right = 0; for (int i = 0; i < childCount; i++) { View itemView = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams(); params.rightMargin = mSize; itemView.setLayoutParams(params); final int left = itemView.getRight(); right = left + mSize; if (i == childCount - 1) right = left; canvas.drawRect(left, top, right, bottom, mPaint); } } private void drawHorizontal(Canvas canvas, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); int childCount = parent.getChildCount(); int bottom = 0; for (int i = 0; i < childCount; i++) { View itemView = parent.getChildAt(i); RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams(); params.bottomMargin = mSize; itemView.setLayoutParams(params); final int top = itemView.getBottom(); bottom = top + mSize; if (i == childCount - 1) bottom = top; canvas.drawRect(left, top, right, bottom, mPaint); } } }
这里重写onDraw 这个方法,针对垂直和水平的布局,都能在每个item 的之间设置间隙。
具体实现原理的页面在这里
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0630/4400.html