Android 自定义HorizontalScrollView实现二级菜单
2017-12-25 16:53
549 查看
Android 自定义HorizontalScrollView实现二级菜单
首先感谢一篇博客对本人的指导,Android 自定义控件打造史上最简单的侧滑菜单 ,十分感谢。最近有一个项目需求是这样的,首先有两个纵向的List,也就是二级菜单,点击主List的项目会打开对应副List中的项目,然后滑动可以隐藏掉主List,同时副List的文字会居中显示。
先来看看效果
MyScrollView
首先重写自定View继承HorizontalScrollView,其中HorizontalScrollView有几个很重要的方法,分别是scrollTo, scrollBy, smoothScrollTo, smoothScrollBy,这里我们用到smoothScrollTo(x, y),即平滑地滑动到,注意,x和y是相对于HorizontalScrollView而不是屏幕。这里我们还要重写onTouchEvent,当手指离开屏幕时判断主List被移出了多少,当移出超过一半时完全显示,少于一半时隐藏。public class MyScrollView extends HorizontalScrollView { /** * 屏幕宽度 */ private int screenWidth; /** * 主list的宽度 */ private int chiefListWidth; private int halfChiefWidth; private boolean once = true; /** * chiefList是否打开 */ private boolean isOpen = false; public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); //获取屏幕宽度 screenWidth = getResources().getDisplayMetrics().widthPixels; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 显示的设置一个宽度 */ if (once) { LinearLayout wrapper = (LinearLayout) getChildAt(0); RecyclerView chiefList = (RecyclerView) wrapper.getChildAt(0); RecyclerView adjunctList = (RecyclerView) wrapper.getChildAt(1); chiefListWidth = screenWidth / 2; halfChiefWidth = chiefListWidth / 2; //设置chiefList的宽度为屏幕的一半 chiefList.getLayoutParams().width = chiefListWidth; //设置adjunctList的宽度为屏幕宽 adjunctList.getLayoutParams().width = screenWidth; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { // 先显示ChiefList this.scrollTo(0, 0); once = false; } } @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { // Up时,进行判断,如果显示区域大于ChiefList宽度一半则完全显示,否则隐藏 case MotionEvent.ACTION_UP: int scrollX = getScrollX(); if (scrollX > halfChiefWidth) { this.smoothScrollTo(chiefListWidth, 0); isOpen = false; } else { this.smoothScrollTo(0, 0); isOpen = true; } //将状态回调出去 if (onChiefListOpenListener != null) { onChiefListOpenListener.onChiefListOpen(isOpen); } return true; } return super.onTouchEvent(ev); } interface OnChiefListOpenListener { void onChiefListOpen(boolean isOpen); } private OnChiefListOpenListener onChiefListOpenListener; public void setOnChiefListOpenListener(OnChiefListOpenListener onChiefListOpenListener) { this.onChiefListOpenListener = onChiefListOpenListener; } }
这里我们还写了个OnChiefListOpenListener接口,其作用是将主List是否在显示的状态回调出去供Adapter使用,因为副List的文本对齐是要用到的。
MyAdapter
RecyclerView要用到的Adapter,这里我们只简单地显示文本,因为主List和副List都用同一个Adapter,故构造时还需传递一个isChief参数。参数isOpen指明当前主List是否打开,如果打开则更新副List让文本居中显示,否则靠左显示。public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { private Context context; private List<String> datas; private boolean isChief; private boolean isOpen = true; public MyAdapter(Context context, List<String> datas, boolean isChief) { this.context = context; this.datas = datas; this.isChief = isChief; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item_double_list, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, final int position) { holder.tvMsg.setText(datas.get(position)); if (!isChief) { //副List if (isOpen) { //主List打开,靠左显示 holder.tvMsg.setGravity(Gravity.LEFT); } else { //主List关闭,居中显示 holder.tvMsg.setGravity(Gravity.CENTER_HORIZONTAL); } } holder.tvMsg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //将点击事件传递给Activity if (onItemClickListener != null) { onItemClickListener.onItemClick(position); } } }); } @Override public int getItemCount() { return datas == null ? 0 : datas.size(); } class ViewHolder extends RecyclerView.ViewHolder { TextView tvMsg; public ViewHolder(View itemView) { super(itemView); tvMsg = itemView.findViewById(R.id.tv_msg); } } public void changeDatas(List<String> datas) { this.datas = datas; notifyDataSetChanged(); } public void changeOpen(boolean isOpen) { this.isOpen = isOpen; notifyDataSetChanged(); } interface OnItemClickListener { void onItemClick(int position); } private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } }
MainActivity
Activity就没什么好讲的了,主要是两个RecyclerView,两个Adapter,三个数据集,其中一个数据集是Map,用来指明主List中每个item对应的副List,相当于一个二维数组。public class MainActivity extends AppCompatActivity { private RecyclerView chiefRecyclerView; private MyAdapter chiefAdapter; private List<String> chiefDatas; private RecyclerView adjunctRecyclerView; private MyAdapter adjunctAdapter; private List<String> adjunctDatas; /** * 主List中每个item对应的副List,相当于一个二维数组 */ private Map<String, List<String>> dataMap; private MyScrollView myScrollView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); chiefRecyclerView = findViewById(R.id.lv_chief); adjunctRecyclerView = findViewById(R.id.lv_adjunct); myScrollView = findViewById(R.id.my_scroll_view); //造数据 chiefDatas = new ArrayList<>(); adjunctDatas = new ArrayList<>(); dataMap = new HashMap<>(); for (int i = 0; i < 20; i++) { String select = "select" + i; chiefDatas.add(select); List<String> tempList = new ArrayList<>(); for (int j = 0; j < 5; j++) { String option = "option" + i + j; tempList.add(option); } dataMap.put(select, tempList); } adjunctDatas = dataMap.get("select0"); //主ListAdapter chiefAdapter = new MyAdapter(this, chiefDatas, true); chiefAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override public void onItemClick(int position) { //变换副List中的数据 adjunctDatas = dataMap.get(chiefDatas.get(position)); adjunctAdapter.changeDatas(adjunctDatas); } }); //副ListAdapter adjunctAdapter = new MyAdapter(this, adjunctDatas, false); adjunctAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(MainActivity.this, adjunctDatas.get(position), Toast.LENGTH_SHORT).show(); } }); //ScrollView中主List的开启状态变化 myScrollView.setOnChiefListOpenListener(new MyScrollView.OnChiefListOpenListener() { @Override public void onChiefListOpen(boolean isOpen) { adjunctAdapter.changeOpen(isOpen); } }); chiefRecyclerView.setAdapter(chiefAdapter); adjunctRecyclerView.setAdapter(adjunctAdapter); chiefRecyclerView.setLayoutManager(new LinearLayoutManager(this)); adjunctRecyclerView.setLayoutManager(new LinearLayoutManager(this)); } }
布局文件
这里主要是activity的布局文件,至于item_double_list主要是一个TextView这里就不粘了。<?xml version="1.0" encoding="utf-8"?> <com.dongyang.doublelistview2.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/my_scroll_view" android:layout_width="wrap_content" android:layout_height="match_parent" tools:context="com.dongyang.doublelistview2.MainActivity"> <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal"> <android.support.v7.widget.RecyclerView android:id="@+id/lv_chief" android:layout_width="100dp" android:layout_height="match_parent" android:background="@color/colorAccent" /> <android.support.v7.widget.RecyclerView 9395 android:id="@+id/lv_adjunct" android:layout_width="200dp" android:layout_height="match_parent" android:background="@color/colorPrimary" /> </LinearLayout> </com.dongyang.doublelistview2.MyScrollView>
到这里一个可以滑动的二级菜单就完成了,谢谢你的观看。
相关文章推荐
- android:自定义HorizontalScrollView实现qq侧滑菜单
- android:自定义HorizontalScrollView实现qq侧滑菜单 标签: HorizontalScrollView自定义viewqq侧滑菜单 2016
- 自定义 view 练习(1):用 HorizontalScrollView 实现自定义侧滑菜单
- Android学习笔记 :自定义HorizontalScrollView实现侧滑菜单
- Android 自定义View修炼-自定义HorizontalScrollView视图实现仿ViewPager效果
- Android 自定义 HorizontalScrollView 实现图片左右滚动按钮控制
- Android_自定义HorizontalScrollView实现滑动子控件大小伸缩
- Android 自定义 HorizontalScrollView 实现ViewPager效果,打造再多图片(控件)也不怕 OOM
- Android 实现横向标题栏滚动效果(HorizontalScrollView + GridView + Viewpager + 自定义适配器)
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
- android自定义Tabs控件,基于ScrollView+ViewPager实现。
- 布局动画Android ScrollView HorizontalScrollView 实现全方向(上下左右)反弹效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 实例讲解HorizontalScrollView实现左右滑动
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android ScrollViewy与HorizontalScrollView实现上下左右滚动