1.需求背景:
需要實現類似淘寶,京東app分類主頁的功能,左側列表是一級標題,右側展示二級標題和三級詳細列表,右側展示列表在底部繼續上可以切換到下一個子分類信息,或者在頂部繼續下拉切換到上一個子分類信息。
效果圖如下:
三級數據數據模型如下:
{
"id":4,
"name":"美妝",
"sname":"美妝",
"level":0,
"parent_id":0,
"logo":null,
"children":[
{
"id":62,
"name":"彩妝",
"sname":"彩妝",
"level":1,
"parent_id":4,
"logo":"https://img.daff9.cn/biyingniao/images/other/1909/5d80d7d33d93a.jpg",
"children":[
{
"id":63,
"name":"彩妝套裝",
"sname":"彩妝套裝",
"level":2,
"parent_id":62,
"logo":"https://img.daff9.cn/biyingniao/images/other/1909/5d8b375dae870.jpg",
"children":[
]
}
]
}
]
}
2.實現思路:
佈局文件中主要分三大塊,頂部搜索框區域較爲簡單,暫時略過,底部分類主內容展示區域通過左側一個recycleview將分類信息中的一級標題展示出來,右側則通過scrollview不斷添加二級分類和三級分類信息,scrollview中每一個子view都是頂部是二級分類標題,列表則是三級分類詳細信息(標題和圖片)。
scrollview子view實現如下:
category_right_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:descendantFocusability="blocksDescendants"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/right_item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:textSize="14sp"
android:textColor="@color/category_main_title_unselect"
android:fontFamily="NotoSansCJKsc-Regular"
android:layout_marginTop="13dp"
android:layout_marginStart="10dp"
android:layout_marginBottom="11dp"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/right_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/right_item_title"
android:background="@drawable/cate_right_flex_bg"
android:paddingBottom="14dp"
/>
</RelativeLayout>
CategoryFlowView.java
public class CategoryFlowView extends LinearLayout {
private static final String TAG = "CategoryFlowView";
private Context context;
private RecyclerView boxLayout;
private TextView title;
private CategorySecondItemBean data;
public CategoryFlowView(Context context) {
this(context, null);
}
public CategoryFlowView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CategoryFlowView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public CategoryFlowView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context cn) {
context = cn;
LayoutInflater inflater = LayoutInflater.from(cn);
View rootView = inflater.inflate(R.layout.category_right_item, this);
title = (TextView) rootView.findViewById(R.id.right_item_title);
boxLayout = (RecyclerView) rootView.findViewById(R.id.right_box);
}
public void setData(CategorySecondItemBean bean) {
this.data = bean;
title.setText(bean.getName());
List<CategoryThirdItemBean> children = bean.getChildren();
if (children != null && children.size() != 0) {
CategoryRecycleAdapter adapter = new CategoryRecycleAdapter(context, children);
GridLayoutManager layoutManager = new GridLayoutManager(context, 3) {
@Override
public boolean canScrollVertically() {
return false;
}
};
boxLayout.setLayoutManager(layoutManager);
boxLayout.setAdapter(adapter);
} else {
this.setVisibility(View.GONE);
}
}
}
ScrollView實現滑動到頂部或者底部後繼續拉動產生回調事件,該功能通過重載onOverScrolled實現:
ScrollView.java中有代碼如下:
@Override
public boolean onTouchEvent(MotionEvent ev) {
......
switch (actionMasked) {
case MotionEvent.ACTION_DOWN:
......
case MotionEvent.ACTION_MOVE:
......
如果是拖動的話
if (mIsBeingDragged) {
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
//調用overScrollBy將會調用onOverScrolled,它將會調用onScrollChanged如果適用的話
if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)
&& !hasNestedScrollingParent()) {
......
}
...
自定義scrollview後重載onOverScrolled,測試中打印日誌發現果然能夠證明之前的猜想,到了頂部或者底部繼續上下拉會調用該接口,遂自定義scrollview如下:
CouponScrollView.java
public class CouponScrollView extends ScrollView {
private OverScrollListener overScrollListener;
private int count = 0;
private boolean top,bottom,overScrolled;
public CouponScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOverScrollListener(OverScrollListener listener) {
this.overScrollListener = listener;
}
public void init() {
count = 0;
top = false;
bottom = false;
overScrolled = false;
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
if(overScrollListener == null) {
return;
}
if(clampedY) {
count++;
} else {
count=0;
}
if(count == 6) {
overScrolled = true;
if(scrollY == 0) {
//滑動到了頂部
top = true;
bottom = false;
} else {
//滑動到了底部
top = false;
bottom = true;
}
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (overScrollListener != null && overScrolled) {
overScrolled = false;
overScrollListener.overScrolled(top,bottom);
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
}
public interface OverScrollListener {
void overScrolled(boolean top, boolean bottom);
}
}
剩下的功能就是從網上或者本地文件中讀取分類信息,將分類信息分別填充到左側的一級標題recycleview中,和填充到CategoryFlowView然後添加到右側的scrollview中,
完整代碼如下:
https://github.com/tenghuihua/category