編輯:關於Android編程
360安全衛士的那個刷新球(姑且叫它刷新球,因為真的不知道叫什麼好,不是dota裡的刷新球!!),裡面像住了水一樣,生動可愛,看似簡單,寫起來不太簡單,本例程只是實現了它的部分功能而已,說實話,跟360的刷新球比起來差距還是很大,我這個長得有點挫。
本歷程需要用到的知識包括:android的自定義View,自定義canvas、path、Bitmap、Handler
先結果演示:
public class MyPathView extends View {
private int width;
private int height;
private int progress;
private int maxProgress = 100;
private Path mPath;
private Paint mPaintCircle;
private Paint mPaintWave;
private Paint mPaintText;
private Bitmap mBitmapBubble;
private Canvas mCanvasBitmap;
private int size = 0;//水波動幅度
private int count;//水流動距離
private boolean isAdd = true;
private static final int START_WAVE = 0x21;
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
public int getMaxProgress() {
return maxProgress;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case START_WAVE:
count += 30;
if (count >= 180) {
count = 0;
}
if (isAdd) {
size += 7;
if (size > 41) {
isAdd = false;
}
} else {
size -= 7;
if (size <= -41) {
isAdd = true;
}
}
invalidate();
sendEmptyMessageDelayed(START_WAVE, 100);
break;
}
}
};
public MyPathView(Context context) {
super(context);
}
public MyPathView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintCircle = new Paint();
mPaintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
mPaintCircle.setColor(Color.argb(0X4f, 0x4d, 0x4d, 0xff));
mPaintText = new Paint();
mPaintText.setColor(Color.WHITE);
mPaintText.setTextSize(50);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintWave = new Paint();
mPaintWave.setColor(Color.argb(0xaa, 0xff, 0x7c, 0x00));
mPaintWave.setStyle(Paint.Style.FILL);
//不顯示非重疊部分,並且重疊部分顯示自己
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP);
mPaintWave.setXfermode(mode);
mPath = new Path();
handler.sendEmptyMessageDelayed(START_WAVE, 1000);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
mBitmapBubble = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvasBitmap = new Canvas(mBitmapBubble);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
//canvas.drawColor(Color.argb(0xaa, 0x88, 0x7e, 0x7f));//自定義顏色
mCanvasBitmap.drawCircle(width / 2, height / 2, 200, mPaintCircle);
mPath.reset();
//用path圈出一個矩形,把水波和球的包含進去
mPath.moveTo(width / 2 + 200, height / 2 + 200 - progress / maxProgress * 400);
mPath.lineTo(width / 2 + 200, height / 2 + 200);
mPath.lineTo(0, height / 2 + 200);
mPath.lineTo(0, height / 2 + 200 - progress / maxProgress * 400);
/*
畫一條個模擬流動的波浪
*/
//當count增大時,重繪會顯示向前流動效果,count的值不能大於width/2-200
mPath.lineTo(count, height / 2 + 200 -(float) progress / maxProgress * 400);
// mPath.moveTo(count,200);
//size的從大到小從小到大變化,重繪時會產生波浪起伏效果
for (int i = 0; i < 20; i++) {
/*
rQuadTo()方法每次都會自動移動到下一位置,參數依次為水平幅度,
垂直幅度,水平位移,處置位移
*/
mPath.rQuadTo(20, size, 90, 0);
mPath.rQuadTo(20, -size, 90, 0);
}
mPath.close();
mCanvasBitmap.drawPath(mPath, mPaintWave);
canvas.drawBitmap(mBitmapBubble, 0, 0, null);
//繪制文本,當前進度
canvas.drawText(progress*100/maxProgress+%,width/2,height/2,mPaintText);
}
}
主活動調用自定義View:
public class MainActivity extends Activity {
private int progress;
private Button mButtonStart;
private MyPathView myPathView;
private static final int DOWNLOAD_UPDATE = 0x99;
//模擬下載
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//處理msg
switch (msg.what) {
case DOWNLOAD_UPDATE:
progress += 1;
//當progress大於maxProgress時,不再調用一下方法
if (progress<=myPathView.getMaxProgress()){
myPathView.setProgress(progress);//設置新的進度
sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 100);//每隔100毫秒發送一次handler
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonStart = (Button) findViewById(R.id.button_start);
myPathView = (MyPathView) findViewById(R.id.progress_view_first);
mButtonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//向handler發送一個延時空消息,1000毫秒後發送
mHandler.sendEmptyMessageDelayed(DOWNLOAD_UPDATE, 1000);
}
});
}
}
我們常用context.startService()來啟動一個service,下面來分析一下這個service的啟動過程,下圖是service啟動的序列圖: st
前言:本篇只是一個介紹這個一個類庫,具體實現思路代碼會下篇中進行分析出來,仿愛奇藝視頻,騰訊視頻,搜狐視頻首頁推薦位輪播圖github地址: https://github
作為Android應用開發者,不得不面對一個尴尬的局面,就是自己辛辛苦苦開發的應用可以被別人很輕易的就反編譯出來。Google似乎也發現了這個問題,從SDK
Android安全加密專題文章索引 Android安全加密:對稱加密 Android安全加密:非對稱加密 Android安全加密:消息摘要Message D