zoukankan      html  css  js  c++  java
  • Android开源系列:仿网易Tab分类排序控件实现

    前言

    产品:网易新闻那个Tab排序好帅。

    开发:哦~

    然后这个东东在几天后就出现了。。。。。

    (PS:差不多一年没回来写博客了~~~~(>_<)~~~~,顺便把名字从 enjoy风铃 修改为 码农叔叔

    效果图

    使用方法

    1、XML布局引入

    <com.net168.lib.SortTabLayout 
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    2、设置数据源数据,也就是每个item的对应文本数据

    1 //构造数据源,暂时仅支持String
    2 List<String> data = new ArrayList<String>();
    3 for (int i = 0; i < 20; i ++) {
    4     data.add("item" + i);
    5 }
    6 //设置数据源
    7 vSortLayout.setShowData(data, 1);

    3、设置监听,用于交互点击和长按的事件

     1 vSortLayout.setOnSelectListener(new onSelectListener() {
     2     //点击事件,点击Tab布局里面的item触发
     3     @Override
     4     public void onSelect(View v, int index) {
     5         Toast.makeText(MainActivity.this, "你点击了item ,内容为:" + ((TextView)v).getText(), Toast.LENGTH_SHORT).show();
     6     }
     7     //长按事件,长按Tab布局里面的item触发
     8     @Override
     9     public void onLongSelect(View v) {
    10         Toast.makeText(MainActivity.this, "长按Tab,开始排列", Toast.LENGTH_SHORT).show();
    11     }
    12 });

    4、开始排序和结束排序的接口

    1 //如果参数是true的话,开始排序,也就是可以拖动
    2 vSortLayout.setIsMoveList(true);
    3 //结束排序,并且会返回选择tab的当前新位置
    4 vSortLayout.getAndFinishSortData();

     5、基本没有其他的了~

    未完善的自定义功能

    1、现在仅仅是支持String,并且布局也无法自定义,后续可能会完善Tab的item的View的自定义输入

    2、现在布局的行数和间距由硬代码控制,并没有形成简便易懂的接口暴漏

    PS:调试间距的方法,主要调试下列几个参数

    /**
     * 配置参数区域
     * mMaxRow : 每行的个数
     * Magin Width Tab的间隔和本身的宽度的占比
     * 例如mMaxRow = 4,则宽度会由此策略分配
     * |Magin|View|Magin|View|Magin|View|Magin|View|Magin|
     * 记控件宽度为这么分配 : 总宽度 = 5 * Magin + 4 * View, 而 Magin : View = mRowMagin : mRowWidth
     * 可以推导出各个控件的宽度,高度也如此计算
     */
    private final int mMaxRow = 4;
    private final int mRowMagin = 5;
    private final int mRowWidth = 26;
    private final int mColumnMagin = 4;
    private final int mColumnHeight = 10;

    3、回滚不流畅,后期可以引入Scroller来控制缓慢回滚


    原理实现

    1、布局item排序采用基于ViewGroup的自定义布局,在onLayout的方法逻辑根据配置参数区域的参数进行计算配置

     1 @Override
     2 protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
     3     
     4     final int childCount = getChildCount();
     5     
     6     int row = 0;
     7     int column = 0;
     8     int startWidth = 0;
     9     int startHeight = 0;
    10     
    11     for (int i = 0; i < childCount; i++) {
    12         View childeView = childList.get(i);
    13         row = i / 4;
    14         column = i % 4;
    15         startWidth = (int) ((column * (mRowWidth + 2 * mRowMagin) + mRowMagin) * mChildeItemSize);
    16         startHeight = (int) ((row * (mColumnHeight + 2 * mColumnMagin) + mColumnMagin) * mChildeItemSize);
    17         childeView.layout(startWidth ,startHeight ,(int)(startWidth + mRowWidth * mChildeItemSize),
    18                  (int)(startHeight + mColumnHeight * mChildeItemSize));
    19     }
    20     
    21 }

    2、滑动模块部分,在onTouchEvent里面根据坐标的捕获,有坐标分析出对应的子Item,利用View.layout()方法让拖动的View跟随手指移动,参加代码

     1 private void moveChildView(float x, float y) {
     2     if (mMoveChildView != null) {
     3         int left = (int) (((mChildIndex % 4) * (mRowWidth + 2 * mRowMagin) + mRowMagin) * mChildeItemSize);
     4         int top = (int) (((mChildIndex / 4) * (mColumnHeight + 2 * mColumnMagin) + mColumnMagin) * mChildeItemSize);
     5         int width = (int) (left + mRowWidth * mChildeItemSize);
     6         int heigth = (int) (top + mColumnHeight * mChildeItemSize);
     7         int moveX = (int) (x - beginX);
     8         int moveY = (int) (y - beginY);
     9         mMoveChildView.layout(left + moveX, top + moveY, width + moveX, heigth + moveY);
    10         mMoveChildView.invalidate();
    11     }
    12 }

    3、动画模块,由于考虑低版本和不想引入过多的开源库,故采用普通的动画实现
    具体参见beginAnimation(final int start,final int end, boolean forward)方法。

    4、整体流程

    a、Touch的down事件,捕捉当前的x、y数据,计算出被移动的View的所对应index,并且其余view开始抖动动画

    b、move事件,将被选中的view根据x、y利用layout方法进行跟随手指移动

    c、up事件,执行位置调整动画,并且在调整完毕后,进行新位置的设置

    结语

    因为懒,所以懒~

    控件是为了需求而写,并没有开源那般易于扩展,后续有时间会进行优化

    github地址:https://github.com/CodeFarmerUncle168/SortTabLayout

    作者:码农叔叔(enjoy风铃)
    出处:http://www.cnblogs.com/net168/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则下次不给你转载了

  • 相关阅读:
    每天一道LeetCode--141.Linked List Cycle(链表环问题)
    每天一道LeetCode--119.Pascal's Triangle II(杨辉三角)
    每天一道LeetCode--118. Pascal's Triangle(杨辉三角)
    CF1277D Let's Play the Words?
    CF1281B Azamon Web Services
    CF1197D Yet Another Subarray Problem
    CF1237D Balanced Playlist
    CF1239A Ivan the Fool and the Probability Theory
    CF1223D Sequence Sorting
    CF1228D Complete Tripartite
  • 原文地址:https://www.cnblogs.com/net168/p/5516666.html
Copyright © 2011-2022 走看看