Android如何用Canvas畫一個(gè)真正能跑的跑馬燈
前言
以前自學(xué),都是用幀動(dòng)畫來實(shí)現(xiàn)跑馬燈,這幾天常失眠,晚上學(xué)東西也學(xué)不進(jìn),所以用Canvas寫個(gè)小Demo,這么無聊的應(yīng)該只有我一個(gè)了吧,廢話不多說,下面上內(nèi)容。
老規(guī)矩,最后有源碼
效果圖如下:

上代碼前先介紹下手機(jī)坐標(biāo)系,如下圖

然后是繪制草圖,如下:

大概思路為,開一個(gè)耗時(shí)線程使彩色背景旋轉(zhuǎn),來達(dá)到跑馬燈的效果。
核心:
1.計(jì)算出View寬高,矩形寬高,從而算出矩形的坐標(biāo)點(diǎn)。
int canvasWidth = canvas.getWidth(); //畫布寬度
int canvasHeight = canvas.getHeight(); //畫布高度
int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2,2)+Math.pow(canvasHeight/2,2))+1; //正方形寬高的一半2.繪制背景,跑馬燈,幕布
//開始繪制底層背景
p.setColor(Color.WHITE);
RectF oval2 = new RectF(0, 0, canvasWidth, canvasHeight);// 設(shè)置個(gè)新的長方形,掃描測量
canvas.drawRect(oval2,p);
//開始繪制跑馬燈
Paint p1=new Paint(p);
Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax,
new int[] { Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
p1.setShader(mShader);
RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// 設(shè)置個(gè)新的長方形
canvas.drawRect(oval,p1);
//繪制幕布
Paint p2=new Paint();
p2.setColor(Color.BLACK);
RectF oval3 = new RectF(30, 30, canvasWidth-30, canvasHeight-30);// 設(shè)置個(gè)新的長方形,掃描測量
canvas.drawRect(oval3,p2);3.找到旋轉(zhuǎn)的依靠,并開啟一個(gè)耗時(shí)任務(wù)。
private Calendar mCalendar; // 時(shí)間對象
public static final int START_CLOCK = 1000;// 開啟時(shí)鐘的標(biāo)識
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case DrawView.START_CLOCK:
mCalendar = mCalendar.getInstance();
invalidate();
sendEmptyMessageDelayed(DrawView.START_CLOCK, 10);
break;
case DrawView.STOP_CLOCK:
break;
default:
break;
}
}
};4.設(shè)置彩色正方形旋轉(zhuǎn)
canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2);
5.將幕布按照彩色正方形反向旋轉(zhuǎn)(不設(shè)置則跟著正方形一起旋轉(zhuǎn));
canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2);
源碼如下:1.完整java文件
public class MarqueeView extends View {
private Calendar mCalendar; // 時(shí)間對象
public static final int START_CLOCK = 1000;// 開啟時(shí)鐘的標(biāo)識
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case DrawView.START_CLOCK:
mCalendar = mCalendar.getInstance();
invalidate();
sendEmptyMessageDelayed(DrawView.START_CLOCK, 10);
break;
case DrawView.STOP_CLOCK:
break;
default:
break;
}
}
};
public MarqueeView(Context context) {
super(context);
}
public MarqueeView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mCalendar = mCalendar.getInstance();
if (mCalendar == null) {
mCalendar = mCalendar.getInstance();
}
mHandler.sendEmptyMessage(START_CLOCK);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawAxis(canvas);
}
//繪制
private void drawAxis(Canvas canvas){
Paint p=new Paint();
int canvasWidth = canvas.getWidth(); //畫布寬度
int canvasHeight = canvas.getHeight(); //畫布高度
int canvansMax= (int) Math.sqrt(Math.pow(canvasWidth/2,2)+Math.pow(canvasHeight/2,2))+1; //正方形寬高的一半
int sec = mCalendar.get(Calendar.SECOND);//得到當(dāng)前秒數(shù)
//開始繪制底層背景
p.setColor(Color.WHITE);
RectF oval2 = new RectF(0, 0, canvasWidth, canvasHeight);// 設(shè)置個(gè)新的長方形,掃描測量
canvas.drawRect(oval2,p);
canvas.rotate(sec*100,canvasWidth/2,canvasHeight/2);
//開始繪制跑馬燈
Paint p1=new Paint(p);
Shader mShader = new LinearGradient(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax,
new int[] { Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW,Color.RED, Color.GREEN,Color.CYAN,Color.MAGENTA,Color.GRAY,Color.BLUE,Color.YELLOW}, null, Shader.TileMode.REPEAT);
p1.setShader(mShader);
RectF oval = new RectF(canvasWidth/2-canvansMax,canvasHeight/2-canvansMax , 2*canvansMax, 2*canvansMax);// 設(shè)置個(gè)新的長方形,掃描測量
canvas.drawRect(oval,p1);
//繪制幕布
Paint p2=new Paint();
canvas.rotate(-sec*100,canvasWidth/2,canvasHeight/2);
p2.setColor(Color.BLACK);
RectF oval3 = new RectF(30, 30, canvasWidth-30, canvasHeight-30);// 設(shè)置個(gè)新的長方形,掃描測量
canvas.drawRect(oval3,p2);
}
}2.xml中調(diào)用
<com................MarqueeView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
總結(jié)
到此這篇關(guān)于Android如何用Canvas畫一個(gè)真正能跑的跑馬燈的文章就介紹到這了,更多相關(guān)Android用Canvas畫跑馬燈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android利用ContentProvider初始化組件的踩坑記錄
做Android SDK開發(fā)的時(shí)候,一般我們會將初始化的方法封裝,然后讓調(diào)用SDK的開發(fā)者在Application的onCreate方法中進(jìn)行初始化,下面這篇文章主要給大家介紹了關(guān)于Android利用ContentProvider初始化組件的踩坑記錄,需要的朋友可以參考下2022-04-04
Android ProgressDialog使用總結(jié)
ProgressDialog 繼承自AlertDialog,AlertDialog繼承自Dialog,實(shí)現(xiàn)DialogInterface接口,本文給大家介紹Android ProgressDialog使用總結(jié)的相關(guān)知識,需要的朋友通過此文一起學(xué)習(xí)吧2016-01-01
Android getActivity()為空的問題解決辦法
這篇文章主要介紹了Android getActivity()為空的問題解決辦法的相關(guān)資料,導(dǎo)致apk空指針崩潰問題,很嚴(yán)重的問題,為了解決這問題,上網(wǎng)搜索了很多資料,需要的朋友可以參考下2017-07-07
Android TextView 去掉自適應(yīng)默認(rèn)的fontpadding的實(shí)現(xiàn)方法
這篇文章主要介紹了Android TextView 去掉自適應(yīng)默認(rèn)的fontpadding的實(shí)現(xiàn)方法的相關(guān)資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09
通過Jetpack Compose實(shí)現(xiàn)雙擊點(diǎn)贊動(dòng)畫效果
這篇文章主要介紹了如何利用Jetpack Compose實(shí)現(xiàn)雙擊點(diǎn)贊動(dòng)畫效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-01-01
Android編程實(shí)現(xiàn)自定義toast示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義toast,結(jié)合簡單實(shí)例形式分析了自定義布局toast核心實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
Android頭像上傳功能的實(shí)現(xiàn)代碼(獲取頭像加剪切)
最近在做一個(gè)頭像上傳的項(xiàng)目,下面小編給大家分享Android頭像上傳功能的實(shí)現(xiàn)代碼,需要的的朋友參考下吧2017-08-08

