美文网首页AndroidAndroid技术知识Android进阶之路
Android三级联动wheel代码分析(二)

Android三级联动wheel代码分析(二)

作者: 许晓北 | 来源:发表于2015-12-18 16:08 被阅读509次

    自定义View的步骤:

    1、自定义View的属性

    2、在View的构造方法中获得我们自定义的属性

    [ 3、重写onMesure ]

    4、重写onDraw

    我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。

    继承View,实现自己想要的组件,那么需要使用到setMeasuredDimension这个方法,这个方法决定了当前View的大小,如果不使用setMeasuredDimension这个方法,那么View的大小将不起作用。

    1

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    // TODO Auto-generated method stub

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    controlWidth = getWidth();

    if (controlWidth != 0) {

    setMeasuredDimension(getWidth(), itemNumber * unitHeight);

    controlWidth = getWidth();

    }

    }

    2

    @Override

    protected void onDraw(Canvas canvas) {

    // TODO Auto-generated method stub

    super.onDraw(canvas);

    //绘制线条

    3

    drawLine(canvas);

    //绘制数据

    4

    drawList(canvas);

    //绘制覆盖板

    5

    drawMask(canvas);

    }

    3

    /**

    * 绘制线条

    *

    * @param canvas

    */

    private void drawLine(Canvas canvas) {

    if (linePaint == null) {

    linePaint = new Paint();

    linePaint.setColor(lineColor);

    //抗锯齿

    linePaint.setAntiAlias(true);

    //设置空心线宽

    linePaint.setStrokeWidth(1f);

     }

    canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + 2,

    controlWidth, controlHeight / 2 - unitHeight / 2 + 2, linePaint);

    canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - 2,

    controlWidth, controlHeight / 2 + unitHeight / 2 - 2, linePaint);

    }

    4


    /**

    * 绘制数据

    *

    * @param canvas

    */

    private synchronized void drawList(Canvas canvas) {

    if (isClearing)

    return;

    try {

    for (ItemObject itemObject : itemList) {

    itemObject.drawSelf(canvas);

    }

    } catch (Exception e) {

    // TODO: handle exception

    }

    5


    /**

    * 绘制遮盖板

    *

    * @param canvas

    */

    private void drawMask(Canvas canvas) {

    //线性渲染

    LinearGradient lg = new LinearGradient(0, 0, 0, maskHight, 0x00f2f2f2,

    0x00f2f2f2, TileMode.MIRROR);

    Paint paint = new Paint();

    paint.setShader(lg);

    canvas.drawRect(0, 0, controlWidth, maskHight, paint);

    LinearGradient lg2 = new LinearGradient(0, controlHeight - maskHight,

    0, controlHeight, 0x00f2f2f2, 0x00f2f2f2, TileMode.MIRROR);

    Paint paint2 = new Paint();

    //设置渲染对象

    paint2.setShader(lg2);

    canvas.drawRect(0, controlHeight - maskHight, controlWidth,

    controlHeight, paint2);

    }

    //LinearGradient  线性渲染 

    public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

    参数x0表示渐变的起始点x坐标;参数y0表示渐变的起始点y坐标;参数x1表示渐变的终点x坐标;参数y1表示渐变的终点y坐标 ;color0表示渐变开始颜色;color1表示渐变结束颜色;参数tile表示平铺方式。Shader.TileMode有3种参数可供选择,分别为CLAMP、REPEAT和MIRROR:

    CLAMP的作用是如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色

    REPEAT的作用是在横向和纵向上以平铺的形式重复渲染位图

    MIRROR的作用是在横向和纵向上以镜像的方式重复渲染位图

    自定义view已经画好。现在接着进行触摸事件

    6

    @Override

    public boolean onTouchEvent(MotionEvent event) {

    // isEnable是否可用

    if (!isEnable)

    return true;

    int y = (int) event.getY();

    switch (event.getAction()) {

    case MotionEvent.ACTION_DOWN:

    /** 是否滑动中 */

    isScrolling = true;

    /** 按下的坐标 */

    downY = (int) event.getY();

    /** 按下的时间 */

    downTime = System.currentTimeMillis();

    break;

    case MotionEvent.ACTION_MOVE:

    //移动距离

    7

    actionMove(y - downY);

    //选择监听

    8

    onSelectListener();

    break;

    case MotionEvent.ACTION_UP:

    // 移动距离的绝对值

    int move = (y - downY);

    move = move > 0 ? move : move * (-1);

    // 判断段时间移动的距离

    /** 短促移动  goonTime=200*//** 短促移动距离  goonDistence=100*/

    if (System.currentTimeMillis() - downTime < goonTime

    && move > goonDistence) {

    10

    goonMove(y - downY);

    } else {

    13

    actionUp(y - downY);

    }

    17

    noEmpty();

    isScrolling = false;

    break;


    default:

    break;
    }

    return true;


    }

    7

    /**

    * 移动的时候

    *

    * @param move

    */

    private void actionMove(int move) {

    for (ItemObject item : itemList) {

    item.move(move);

     }

    invalidate();

    }

    8

    /**

    * 滑动监听

    */

    private void onSelectListener() {

    /** 选择监听 */

    9

    if (onSelectListener == null)

    return;

    for (ItemObject item : itemList) {

    if (item.isSelected()) {

    //监听选择

    onSelectListener.selecting(item.id, item.itemText);

    }

    }

    }


    设置监听接口回调

    9


    /**

    * 选择监听监听

    *

    * @author zoudong

    *

    */

    public interface OnSelectListener {

    /**

    * 结束选择

    *

    * @param id

    * @param text

    */

    public void endSelect(int id, String text);

    /**

    * 选中的内容

    *

    * @param id

    * @param text

    */

    public void selecting(int id, String text);

    }

    10

    /**

    * 继续移动一定距离

    */

    private synchronized void goonMove(final int move) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    // TODO Auto-generated method stub

    int distence = 0;

    /** 移动距离  MOVE_NUMBER=5*/

    while (distence < unitHeight * MOVE_NUMBER) {

    try {

    Thread.sleep(5);

     } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

     }

    11

    actionThreadMove(move > 0 ? distence : distence * (-1));

    distence += 10;
     }    13
    actionUp(move > 0 ? distence - 10 : distence * (-1) + 10);
    17
    noEmpty();

     }
     }).start();
    }

    /*  11

    * 移动,线程中调用

    *

    * @param move

    */

    private void actionThreadMove(int move) {

    for (ItemObject item : itemList) {

    item.move(move);

    }

    12

    Message rMessage = new Message();

    /** 刷新界面  REFRESH_VIEW=0x001 */

    rMessage.what = REFRESH_VIEW;

    handler.sendMessage(rMessage);
    }

    12

    @SuppressLint("HandlerLeak")

    Handler handler = new Handler() {

    @Override

    public void handleMessage(Message msg) {

    // TODO Auto-generated method stub

    super.handleMessage(msg);

    switch (msg.what) {

    case REFRESH_VIEW:

    invalidate();

    break;

    default:

    break;

       }

     }

    };

    13

    /**

    * 松开的时候

    *

    * @param move

    */

    private void actionUp(int move) {

    int newMove = 0;

    if (move > 0) {

    for (int i = 0; i < itemList.size(); i++) {

    if (itemList.get(i).isSelected()) {

    14

    newMove = (int) itemList.get(i).moveToSelected();

    if (onSelectListener != null)

    //接口回调 结束选择

    onSelectListener.endSelect(itemList.get(i).id,

    itemList.get(i).itemText);

    break;

      }

      }

      } else {

    for (int i = itemList.size() - 1; i >= 0; i--) {

    if (itemList.get(i).isSelected()) {

    newMove = (int) itemList.get(i).moveToSelected();

    if (onSelectListener != null)

    //结束选择

    onSelectListener.endSelect(itemList.get(i).id,

    itemList.get(i).itemText);

    break;

      }

      }

      }

    for (ItemObject item : itemList) {

    15

    item.newY(move + 0);

        }

    16

    slowMove(newMove);

    Message rMessage = new Message();

    rMessage.what = REFRESH_VIEW;

    handler.sendMessage(rMessage);

    }

    14

    /**

    * 获取移动到标准位置需要的距离

    */

    public float moveToSelected() {

    return (controlHeight / 2 - unitHeight / 2) - (y + move);

    }

    15

    /**

    * 设置新的坐标

    *

    * @param move

    */

    public void newY(int _move) {

    this.move = 0;

    this.y = y + _move;

    }

    16

    /**

    * 缓慢移动

    *

    * @param move

    */

    private synchronized void slowMove(final int move) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    // TODO Auto-generated method stub

    // 判断正负

    int m = move > 0 ? move : move * (-1);

    int i = move > 0 ? 1 : (-1);

    // 移动速度

    int speed = 1;

    while (true) {

    m = m - speed;

    if (m <= 0) {

    for (ItemObject item : itemList) {

    item.newY(m * i);

     }

    Message rMessage = new Message();

    rMessage.what = REFRESH_VIEW;

    handler.sendMessage(rMessage);

    try {

    Thread.sleep(2);

     } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

     }

    break;

     }

    for (ItemObject item : itemList) {

    item.newY(speed * i);

     }

    Message rMessage = new Message();

    rMessage.what = REFRESH_VIEW;

    handler.sendMessage(rMessage);

    //释放系统资源

    try {

    Thread.sleep(2);

     } catch (InterruptedException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

     }

     }

    for (ItemObject item : itemList) {

    if (item.isSelected()) {

    if (onSelectListener != null)

    onSelectListener.endSelect(item.id, item.itemText);

    break;

     }

     }

     }

     }).start();

    }

    17

    /**

    * 不能为空,必须有选项

    */

    private void noEmpty() {

    if (!noEmpty)

    return;

    for (ItemObject item : itemList) {

    if (item.isSelected())

    return;

     }

    int move = (int) itemList.get(0).moveToSelected();

    if (move < 0) {

    18

    defaultMove(move);h

     } else {

    defaultMove((int) itemList.get(itemList.size() - 1)

    .moveToSelected());

     }

    for (ItemObject item : itemList) {

    if (item.isSelected()) {

    if (onSelectListener != null)

    onSelectListener.endSelect(item.id, item.itemText);

    break;

     }

     }

    }

    18

    /**

    * 移动到默认位置

    *

    * @param move

    */

    private void defaultMove(int move) {

    for (ItemObject item : itemList) {

    item.newY(move);

     }

    Message rMessage = new Message();

    rMessage.what = REFRESH_VIEW;

    handler.sendMessage(rMessage);

    }

    到了这一步 基本自定义控件搞定了 剩下就是暴漏一些自己需要的接口或者方法了~源码请查看

    Android三级联动wheel代码分析(一)里面,等两天接着Android三级联动wheel代码分析(三)。

    如有不对的地方请指正,因为这个代码较多 加上数字应该会看的稍微清楚点。。。


    相关文章

      网友评论

      本文标题:Android三级联动wheel代码分析(二)

      本文链接:https://www.haomeiwen.com/subject/lcjphttx.html