Android三級聯(lián)動wheel代碼分析(二)

自定義View的步驟:

1、自定義View的屬性

2、在View的構(gòu)造方法中獲得我們自定義的屬性

[?3、重寫onMesure ]

4、重寫onDraw

我把3用[]標(biāo)出了,所以說3不一定是必須的,當(dāng)然了大部分情況下還是需要重寫的。

繼承View,實現(xiàn)自己想要的組件,那么需要使用到setMeasuredDimension這個方法,這個方法決定了當(dāng)前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);

//繪制數(shù)據(jù)

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);

//設(shè)置空心線寬

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


/**

* 繪制數(shù)據(jù)

*

* @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();

//設(shè)置渲染對象

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)

參數(shù)x0表示漸變的起始點x坐標(biāo);參數(shù)y0表示漸變的起始點y坐標(biāo);參數(shù)x1表示漸變的終點x坐標(biāo);參數(shù)y1表示漸變的終點y坐標(biāo)?。籧olor0表示漸變開始顏色;color1表示漸變結(jié)束顏色;參數(shù)tile表示平鋪方式。Shader.TileMode有3種參數(shù)可供選擇,分別為CLAMP、REPEAT和MIRROR:

CLAMP的作用是如果渲染器超出原始邊界范圍,則會復(fù)制邊緣顏色對超出范圍的區(qū)域進行著色

REPEAT的作用是在橫向和縱向上以平鋪的形式重復(fù)渲染位圖

MIRROR的作用是在橫向和縱向上以鏡像的方式重復(fù)渲染位圖

自定義view已經(jīng)畫好。現(xiàn)在接著進行觸摸事件

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;

/** 按下的坐標(biāo) */

downY = (int) event.getY();

/** 按下的時間 */

downTime = System.currentTimeMillis();

break;

case MotionEvent.ACTION_MOVE:

//移動距離

7

actionMove(y - downY);

//選擇監(jiān)聽

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

/**

* 滑動監(jiān)聽

*/

private void onSelectListener() {

/** 選擇監(jiān)聽 */

9

if (onSelectListener == null)

return;

for (ItemObject item : itemList) {

if (item.isSelected()) {

//監(jiān)聽選擇

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

}

}

}


設(shè)置監(jiān)聽接口回調(diào)

9


/**

* 選擇監(jiān)聽監(jiān)聽

*

* @author zoudong

*

*/

public interface OnSelectListener {

/**

* 結(jié)束選擇

*

* @param id

* @param text

*/

public void endSelect(int id, String text);

/**

* 選中的內(nèi)容

*

* @param id

* @param text

*/

public void selecting(int id, String text);

}

10

/**

* 繼續(xù)移動一定距離

*/

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

* 移動,線程中調(diào)用

*

* @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)

//接口回調(diào) 結(jié)束選擇

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)

//結(jié)束選擇

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

/**

* 獲取移動到標(biāo)準(zhǔn)位置需要的距離

*/

public float moveToSelected() {

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

}

15

/**

* 設(shè)置新的坐標(biāo)

*

* @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

// 判斷正負(fù)

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);

//釋放系統(tǒng)資源

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

/**

* 移動到默認(rèn)位置

*

* @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三級聯(lián)動wheel代碼分析(一)里面,等兩天接著Android三級聯(lián)動wheel代碼分析(三)。

如有不對的地方請指正,因為這個代碼較多 加上數(shù)字應(yīng)該會看的稍微清楚點。。。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容