




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
【移動應用開發(fā)技術】Android怎樣仿華為天氣繪制刻度盤
Android怎樣仿華為天氣繪制刻度盤,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。效果圖可以看到這個自定義控件結合了顏色漸變、動態(tài)繪制刻度、動態(tài)水球效果。接下來我們就來看看這個效果是如何一步一步實現的。開始自定義控件和很多自定義控件方式一樣需要去基礎某種View或者某種ViewGroup我這里選擇的是View,如下所示:public
class
HuaWeiView
extends
View
{
/**
*
用來初始化畫筆等
*
@param
context
*
@param
attrs
*/
public
HuaWeiView(Context
context,
@Nullable
AttributeSet
attrs)
{
super(context,
attrs);
}
/**
*
用來測量限制view為正方形
*
@param
widthMeasureSpec
*
@param
heightMeasureSpec
*/
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
}
/**
*
實現各種繪制功能
*
@param
canvas
*/
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
}
}其中構造方法用來布局中使用。onMeasure()方法用來測量和限定view大小onDraw()方法用來進行具體的繪制功能1.使用onMeasure()方法將View限制為一個正方形只有確定了一個矩形才能夠去畫橢圓,如果這個矩形是正方形,橢圓也就隨之變成了圓形。@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
width=MeasureSpec.getSize(widthMeasureSpec);
int
height
=
MeasureSpec.getSize(heightMeasureSpec);
//以最小值為正方形的長
len=Math.min(width,height);
//設置測量高度和寬度(必須要調用,不然無效果)
setMeasuredDimension(len,len);
}分別通過MeasureSpec取得用戶設置的寬和高,然后取出最小值,設置給我們的view,這樣我們就做好了一個矩形現在使用在布局中:<?xml
version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="/apk/res/android"
xmlns:app="/apk/res-auto"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimary"
android:padding="20dp"
tools:context="com.example.huaweiview.MainActivity">
<com.example.huaweiview.HuaWeiView
android:layout_gravity="center"
android:background="@color/colorAccent"
android:layout_width="200dp"
android:layout_height="300dp"
/>
</LinearLayout>父布局背景為藍色背景,控件背景為粉色背景,而且設置的寬高不同,但是控件的顯示效果還是一個正方形,而且以小值為準。我們的onMeasure()生效了接下來就是如何在確定一個圓形區(qū)域了2.onDraw()繪制圓形區(qū)域繪制之前我們需要對Android中的坐標系有個了解我們都知道手機屏幕左上角為坐標原點,往右為X正軸,往下為Y正軸。其實手機頁面就是activity的展示界面,也是一個View。那可不可以說所有的View在繪制圖形的時候都有自己的這么一個坐標系呢(個人想法。。。)也就是所每個View都有自己的一個坐標系,比如現在的自定義View:現在我們需要在我們自定義的view中繪制一個圓弧,那么這個圓弧的半徑就是我們自定義view的長度的一半,即:radius=len/2;那么圓心的坐標剛好是(radius,radius)接下來開始繪制@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
//畫圓弧的方法
canvas.drawArc(oval,
startAngle,
sweepAngle,
useCenter,paint);
}介紹一下繪制圓弧的方法:參數一oval是一個RectF對象為一個矩形參數二startAngle為圓弧的起始角度參數三sweepAngle為圓弧的經過角度(掃過角度)參數四useCenter為圓弧是一個boolean值,為true時畫的是圓弧,為false時畫的是割弧參數五paint為一個畫筆對象也就是說只要確定了一個矩形,在確定他起始和經過的角度就能夠畫出一個圓弧(這點大家可以用畫板測試)下來就是初始化這些參數初始化矩形@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
width
=
MeasureSpec.getSize(widthMeasureSpec);
int
height
=
MeasureSpec.getSize(heightMeasureSpec);
//以最小值為正方形的長
len
=
Math.min(width,
height);
//實例化矩形
oval=new
RectF(0,0,len,len);
//設置測量高度和寬度(必須要調用,不然無效果)
setMeasuredDimension(len,
len);
}畫矩形需要確定左上角和右下角的坐標(通過畫板可以測試),通過上面的分析坐標原點就是我們view的左上角,右下角的坐標當然就是len了。接下來就是初始化起始和經過角度private
float
startAngle=120;
private
float
sweepAngle=300;需要搞清楚往下為Y軸正軸,剛好和上學時候學的相反,也就是說90度在下方,-90度在上方初始化畫筆public
HuaWeiView(Context
context,
@Nullable
AttributeSet
attrs)
{
super(context,
attrs);
paint
=new
Paint();
//設置畫筆顏色
paint.setColor(Color.WHITE);
//設置畫筆抗鋸齒
paint.setAntiAlias(true);
//讓畫出的圖形是空心的(不填充)
paint.setStyle(Paint.Style.STROKE);
}useCenter=false到這里真不容易呀,然而發(fā)現只畫個圓弧沒用呀,我要的是刻度線呀,canvas里面又沒用給我們提供畫刻度線的方法,這個時候就需要我們自己去寫一個畫刻度線的方法了。通過觀察圖片我們可以看出,所有的線都是從圓弧上的點為起點向某個方向畫一條直線,那么該如何確定這兩個點呢,需要我們做兩件事:移動坐標系@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
//畫圓弧的方法
canvas.drawArc(oval,
startAngle,
sweepAngle,
useCenter,paint);
//畫刻度線的方法
drawViewLine(canvas);
}
private
void
drawViewLine(Canvas
canvas)
{
//先保存之前canvas的內容
canvas.save();
//移動canvas(X軸移動距離,Y軸移動距離)
canvas.translate(radius,radius);
//操作完成后恢復狀態(tài)
canvas.restore();
}我們自己寫了一個繪制刻度線的方法并在onDraw()方法中調用。移動坐標系之前需要保存之前的canvas狀態(tài),然后X和Y軸分別移動圓弧半徑的距離,如下圖:canvas.translate(radius,radius);方法移動的是坐標系(通過實際效果和查資料所得)canvas.save()和canvas.restore()要成對出現,就好像流用完要關閉一樣。***件事情完成后,開始第二件事情,旋轉坐標系只通過移動坐標系,仍然很難確定圓弧點上的坐標,和另外一點的坐標,如果這兩個點都在坐標軸上該多好呀,下面實現:private
void
drawViewLine(Canvas
canvas)
{
//先保存之前canvas的內容
canvas.save();
//移動canvas(X軸移動距離,Y軸移動距離)
canvas.translate(radius,radius);
//旋轉坐標系
canvas.rotate(30);
//操作完成后恢復狀態(tài)
canvas.restore();畫刻度線的方法了增加了一個旋轉30度的代碼,旋轉后的坐標系應該怎么樣呢;因為起始點和90度相差30,旋轉之后,起始點剛好落在了Y軸上,那么這個點的坐標就很好確定了吧,沒錯就是(0,radius);如果我們在Y軸上在找一點不就可以畫出一條刻度線了嗎,那么它的坐標是多少呢?對,應該是(0,radius-y),因為我們要往內部化刻度線,因此是減去一個值,趕快去試試吧,代碼如下:private
void
drawViewLine(Canvas
canvas)
{
//先保存之前canvas的內容
canvas.save();
//移動canvas(X軸移動距離,Y軸移動距離)
canvas.translate(radius,radius);
//旋轉坐標系
canvas.rotate(30);
Paint
linePatin=new
Paint();
//設置畫筆顏色
linePatin.setColor(Color.WHITE);
//線寬
linePatin.setStrokeWidth(2);
//設置畫筆抗鋸齒
linePatin.setAntiAlias(true);
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,linePatin);
//操作完成后恢復狀態(tài)
canvas.restore();
}根據得到的兩個點的坐標,畫出來一條白線,如圖:當然這些點都是移動后的坐標系在旋轉30度得到的,這里畫好了一條線,如果畫多條呢,還是剛才的思路每次都讓它旋轉一個小角度然后畫條直線不就好了嗎,那么旋轉多少度呢,比如這里:總共掃過的角度sweepAngle=300;需要100條刻度,那么每次需要旋轉的角度rotateAngle=sweepAngle/100,具體代碼如下:private
void
drawViewLine(Canvas
canvas)
{
//先保存之前canvas的內容
canvas.save();
//移動canvas(X軸移動距離,Y軸移動距離)
canvas.translate(radius,radius);
//旋轉坐標系
canvas.rotate(30);
Paint
linePatin=new
Paint();
//設置畫筆顏色
linePatin.setColor(Color.WHITE);
//線寬
linePatin.setStrokeWidth(2);
//設置畫筆抗鋸齒
linePatin.setAntiAlias(true);
//確定每次旋轉的角度
float
rotateAngle=sweepAngle/99;
for(int
i=0;i<100;i++){
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,linePatin);
canvas.rotate(rotateAngle);
}
//操作完成后恢復狀態(tài)
canvas.restore();
}100個刻度,需要101次循環(huán)畫線(請看你的手表),畫完線就旋轉。依次循環(huán),如圖經過這么久的時間總于完成了刻度盤了,接下來就是去確定不同角度顯示什么樣的顏色,***我們需要確定要繪制的范圍targetAngle:繪制有色部分private
void
drawViewLine(Canvas
canvas)
{
//先保存之前canvas的內容
canvas.save();
//移動canvas(X軸移動距離,Y軸移動距離)
canvas.translate(radius,radius);
//旋轉坐標系
canvas.rotate(30);
Paint
linePatin=new
Paint();
//設置畫筆顏色
linePatin.setColor(Color.WHITE);
//線寬
linePatin.setStrokeWidth(2);
//設置畫筆抗鋸齒
linePatin.setAntiAlias(true);
//確定每次旋轉的角度
float
rotateAngle=sweepAngle/100;
//繪制有色部分的畫筆
Paint
targetLinePatin=new
Paint();
targetLinePatin.setColor(Color.GREEN);
targetLinePatin.setStrokeWidth(2);
targetLinePatin.setAntiAlias(true);
//記錄已經繪制過的有色部分范圍
float
hasDraw=0;
for(int
i=0;i<=100;i++){
if(hasDraw<=targetAngle&&targetAngle!=0){//需要繪制有色部分的時候
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,targetLinePatin);
}else
{//不需要繪制有色部分
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,linePatin);
}
//累計繪制過的部分
hasDraw+=rotateAngle;
//旋轉
canvas.rotate(rotateAngle);
}
//操作完成后恢復狀態(tài)
canvas.restore();
}我們需要不斷的去記錄繪制過的有效部分,之外的部分畫白色。根據角度的比例,顏色漸變需要計算出已經繪制過的角度占總角度(300)的比例for(int
i=0;i<=100;i++){
if(hasDraw<=targetAngle&&targetAngle!=0){//需要繪制有色部分的時候
//計算已經繪制的比例
float
percent=hasDraw/sweepAngle;
int
red=
255-(int)
(255*percent);
int
green=
(int)
(255*percent);
targetLinePatin.setARGB(255,red,green,0);
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,targetLinePatin);
}else
{//不需要繪制有色部分
//畫一條刻度線
canvas.drawLine(0,radius,0,radius-40,linePatin);
}
hasDraw+=rotateAngle;
canvas.rotate(rotateAngle);
}只是在繪制有色部分的時候,利用三元素來實現漸變。所占比例越低紅色值越大,反正綠色值越大。實現動態(tài)顯示先想一下它的運動情況,分為前進狀態(tài)和后退狀態(tài),如果正在運動(一次完整的后退和前進沒用結束),就不能開始下次運動,需要兩個參數,state和isRunning//判斷是否在動
private
boolean
isRunning;
//判斷是回退的狀態(tài)還是前進狀態(tài)
private
int
state
=
1;
public
void
changeAngle(final
float
trueAngle)
{
if
(isRunning){//如果在動直接返回
return;
}
final
Timer
timer
=
new
Timer();
timer.schedule(new
TimerTask()
{
@Override
public
void
run()
{
switch
(state)
{
case
1://后退狀態(tài)
isRunning=true;
targetAngle
-=
3;
if
(targetAngle
<=
0)
{//如果回退到0
targetAngle
=
0;
//改為前進狀態(tài)
state
=
2;
}
break;
case
2://前進狀態(tài)
targetAngle
+=
3;
if
(targetAngle
>=
trueAngle)
{//如果增加到指定角度
targetAngle
=
trueAngle;
//改為后退狀態(tài)
state
=
1;
isRunning=false;
//結束本次運動
timer.cancel();
}
break;
default:
break;
}
//重新繪制(子線程中使用的方法)
postInvalidate();
}
},
500,
30);
}利用時間任務,每個30毫秒去執(zhí)行一次run方法,每次都重新繪制圖片,然后在activity中調用此方法HuaWeiView
hwv;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hwv=
(HuaWeiView)
findViewById(R.id.hwv);
hwv.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
v)
{
//點擊事件中,調用動的方法
hwv.changeAngle(200);
}
});
}看到這里了,相信你對坐標系和角度動態(tài)變化,以及刻度盤的繪制有了個很好的認識,多多驗證會有助于理解。接下來要實現背景動態(tài)漸變想想咱們的view中哪里用了漸變呢?對,在繪制有色部分的時候,如果我們能將顏色漸變的值不斷的傳到activity中該多好呀,下面就要用接口傳值實現這一功能了:***在自定義View中聲明一個內部接口:private
OnAngleColorListener
onAngleColorListener;
public
void
setOnAngleColorListener(OnAngleColorListener
onAngleColorListener)
{
this.onAngleColorListener
=
onAngleColorListener;
}
public
interface
OnAngleColorListener{
void
colorListener(int
red,int
green);
}我們在自定義View中聲明一個內部接口,并聲明一個全局接口對象,提供一個set方法接口內有個方法用來獲取顏色值接下來就是在合適的地方調用這個方法,那么哪里呢,就是我們繪制顏色刻度時調用:for
(int
i
=
0;
i
<=
100;
i++)
{
if
(hasDraw
<=
targetAngle
&&
targetAngle
!=
0)
{//需要繪制有色部分的時候
//計算已經繪制的比例
float
percent
=
hasDraw
/
sweepAngle;
int
red
=
255
-
(int)
(255
*
percent);
int
green
=
(int)
(255
*
percent);
//實現接口回調,傳遞顏色值
if
(onAngleColorListener!=null){
onAngleColorListener.colorListener(red,green);
}
targetLinePatin.setARGB(255,
red,
green,
0);
//畫一條刻度線
canvas.drawLine(0,
radius,
0,
radius
-
40,
targetLinePatin);
}
else
{//不需要繪制有色部分
//畫一條刻度線
canvas.drawLine(0,
radius,
0,
radius
-
40,
linePatin);
}我們在繪制的時候實現了接口回調,接下來去activity中實現接口public
class
MainActivity
extends
AppCompatActivity
{
HuaWeiView
hwv;
LinearLayout
ll_parent;
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hwv=
(HuaWeiView)
findViewById(R.id.hwv);
//實例父布局
ll_parent=
(LinearLayout)
findViewById(R.id.ll_parent);
hwv.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
v)
{
//點擊事件中,調用動的方法
hwv.changeAngle(200);
}
});
//設置角度顏色變化監(jiān)聽
hwv.setOnAngleColorListener(new
HuaWeiView.OnAngleColorListener()
{
@Override
public
void
colorListener(int
red,
int
green)
{
Color
color=new
Color();
//通過Color對象將RGB值轉為int類型
int
backColor=color.argb(100,red,green,0);
//父布局設置背景
ll_parent.setBackgroundColor(backCol
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 太湖創(chuàng)意職業(yè)技術學院《康復科護理學》2023-2024學年第二學期期末試卷
- 2024-2025學年陜西省西安市西咸新區(qū)空港新城四年級數學第二學期期末監(jiān)測模擬試題含解析
- 東北財經大學《國際私法》2023-2024學年第二學期期末試卷
- 平頂山學院《化工設備與機械》2023-2024學年第二學期期末試卷
- 2025年02月聊城高唐縣事業(yè)單位初級綜合類崗位人員(10人)筆試歷年典型考題(歷年真題考點)解題思路附帶答案詳解
- 褥瘡護理個案報道
- 負壓治療技術護理
- 食堂工人勞務合同范本
- 美容面部護理講課
- 私人育兒嫂合同范本
- 2025年黑龍江民族職業(yè)學院單招職業(yè)技能測試題庫必考題
- 《CAD發(fā)展歷程》課件
- 統(tǒng)編版語文八年級下冊全冊大單元整體教學設計表格式教案
- 2023年新改版教科版科學三年級下冊活動手冊參考答案(word可編輯)
- 施工方案(行車拆除)
- 開網店全部流程PPT課件
- 《春》帶拼音
- 真速通信密拍暗訪取證系統(tǒng)分冊
- 質量監(jiān)督檢查整改回復單格式(共4頁)
- 淺談一年級數學計算教學的有效策略
- FPC產品簡介及設計規(guī)范
評論
0/150
提交評論