RecycleView
以前一直用ListView,因为ListView可以搞定绝大部分需求。最近项目UI做了很大调整,需要宽度不同的Item混排,记录一下遇到的问题。
类似这样效果
宽度不同的Item混排-SpanSizeLookup
这个很简单,一个方法就搞定了
int maxSpanSize = 2;
GridLayoutManager manager = new GridLayoutManager(mContext, maxSpanSize, GridLayoutManager.VERTICAL, false);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
HomeItemInfo itemInfo = homeItemInfoList.get(position);
if (itemInfo.isTwoItem()) {
return 1;// 1/maxSpanSize, 这里代表占最大宽度的1/2
} else {
return 2;// 2/maxSpanSize, 这里代表与最大宽度等宽
}
}
});
分割线 ItemDecoration
- onDrawOver
绘制在图层的最上层 - onDraw
绘制图层在ItemView以下,所以如果绘制区域与ItemView区域相重叠,会被遮挡 - getItemOffsets
设置ItemView的内嵌偏移长度
RecycleView的ItemDecoration 用起来比ListView的Divider还是复杂很多。
如果只用做透明的分割线,复写getItemOffsets就可以实现了。列表本身如果对分割线的不敏感,复写onDrawOver就可以。一些复杂的分割线需要同时复写getItemOffsets、onDrawOver,计算还是有些麻烦的。下面分享下getItemOffsets的计算。
public class RecycleDivider extends RecyclerView.ItemDecoration {
private int rightMargin = 100;//px, item距离右边的margin
private int leftMargin = 100;//px, item距离左边的margin
private int verticalDivider = 20;//px, 竖直方向分割线的宽度
private int horizontalDivider = 10;//px, 水平方向分割线的宽度
private List<HomeItemInfo> itemInfos = new ArrayList<>();
public RecycleDivider() {
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
GridLayoutManager.SpanSizeLookup lookup = layoutManager.getSpanSizeLookup();
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) view.getLayoutParams();
int childPosition = parent.getChildAdapterPosition(view);
int spanCount = layoutManager.getSpanCount();
int position = parent.getChildAdapterPosition(view);//得到它在总数里面的位置
int spanIndex = lookup.getSpanIndex(position, layoutManager.getSpanCount());//获取每排的位置
int spanSize = lookup.getSpanSize(position);//获取它所占有的比重,上面讲的
if (layoutManager.getOrientation() == GridLayoutManager.VERTICAL) {//这里只处理竖直方向的列表
//竖直方向
if (layoutManager.getSpanSizeLookup().getSpanGroupIndex(childPosition, spanCount) == 0) {//第一排的需要上面
outRect.top = horizontalDivider;
}
outRect.bottom = horizontalDivider;
//水平方向,这里只适合一行两个item的情况
//每个item的宽度是均分的,如果每个item的outRect.left, outRect.right加起来的和不一样,会导致item大小不一致
outRect.left = verticalDivider / 2;
outRect.right = verticalDivider / 2;
boolean isRight = spanIndex + spanSize == spanCount;//最右
boolean isLeft = spanIndex == 0;//最左
if (isLeft) {
outRect.left = leftMargin;
}
if (isRight) {
outRect.right = rightMargin;
}
}
}
}
Elevation
Android从5.0开始支持阴影,5.0之前可以用CardView,但是CardView用padding实现,对界面会有影响,可以只在5.0以上支持阴影。
- 阴影是子View打在父View上的
- 子View必须设置Background
- 父View必须比子View稍大一些,父View不要用padding,在子View上用Margin属性
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="10dp"
android:background="#ffffff"
android:elevation="4dp" />
</RelativeLayout>