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

自定义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代码分析(三)。

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


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容