Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
.相關方法詳解
1)Paint(畫筆):
就是畫筆,用于設置繪制風格,如:線寬(筆觸粗細),顏色,透明度和填充風格等 直接使用無參構造方法就可以創建Paint實例: Paint paint = new Paint( );
我們可以通過下述方法來設置Paint(畫筆)的相關屬性,另外,關于這個屬性有兩種, 圖形繪制相關與文本繪制相關:
2)Canvas(畫布):
畫筆有了,接著就到畫布(Canvas),總不能憑空作畫是吧~常用方法如下:
首先是構造方法,Canvas的構造方法有兩種:
Canvas(): 創建一個空的畫布,可以使用setBitmap()方法來設置繪制具體的畫布。
Canvas(Bitmap bitmap): 以bitmap對象創建一個畫布,將內容都繪制在bitmap上,因此bitmap不得為null。
接著是 1.drawXXX()方法族:以一定的坐標值在當前畫圖區域畫圖,另外圖層會疊加, 即后面繪畫的圖層會覆蓋前面繪畫的圖層。 比如:
2.clipXXX()方法族:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個畫圖區域就是canvas 對象的當前畫圖區域了。比如:clipRect(new Rect()),那么該矩形區域就是canvas的當前畫圖區域
3.save()和restore()方法: save( ):用來保存Canvas的狀態。save之后,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作! restore():用來恢復Canvas之前保存的狀態。防止save后對Canvas執行的操作對后續的繪制有影響。 save()和restore()要配對使用(restore可以比save少,但不能多),若restore調用次數比save多,會報錯!
4.translate(float dx, float dy): 平移,將畫布的坐標原點向左右方向移動x,向上下方向移動y.canvas的默認位置是在(0,0)
5.scale(float sx, float sy):擴大,x為水平方向的放大倍數,y為豎直方向的放大倍數
6.rotate(float degrees):旋轉,angle指旋轉的角度,順時針旋轉
3)Path(路徑)
簡單點說就是描點,連線~在創建好我們的Path路徑后,可以調用Canvas的drawPath(path,paint) 將圖形繪制出來~常用方法如下:
更高級的效果可以使用PathEffect類!
幾個To:
2.動手試試:
屬性那么多,肯定要手把手的擼一下,才能加深我們的映像是吧~ 嘿嘿,畫圖要么在View上畫,要么在SurfaceView上畫,這里我們在View上畫吧, 我們定義一個View類,然后再onDraw()里完成繪制工作!
/**
* Created by Jay on 2015/10/15 0015.
*/
public class MyView extends View{
private Paint mPaint;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true); //抗鋸齒
mPaint.setColor(getResources().getColor(R.color.puple));//畫筆顏色
mPaint.setStyle(Paint.Style.FILL); //畫筆風格
mPaint.setTextSize(36); //繪制文字大小,單位px
mPaint.setStrokeWidth(5); //畫筆粗細
}
//重寫該方法,在這里繪圖
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
然后布局那里設置下這個View就好,下述代碼都寫在onDrawable中~
1)設置畫布顏色:
canvas.drawColor(getResources().getColor(R.color.yellow)); //設置畫布背景顏色
2)繪制圓形:
canvas.drawCircle(200, 200, 100, mPaint); //畫實心圓
3)繪制矩形:
canvas.drawRect(0, 0, 200, 100, mPaint); //畫矩形
4)繪制Bitmap:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher), 0, 0, mPaint);
5)繪制弧形區域:
canvas.drawArc(new RectF(0, 0, 100, 100),0,90,true,mPaint); //繪制弧形區域
假如true改為false:
6)繪制圓角矩形
canvas.drawRoundRect(new RectF(10,10,210,110),15,15,mPaint); //畫圓角矩形
7)繪制橢圓
canvas.drawOval(new RectF(0,0,200,300),mPaint); //畫橢圓
8)繪制多邊形:
Path path = new Path();
path.moveTo(10, 10); //移動到 坐標10,10
path.lineTo(100, 50);
path.lineTo(200,40);
path.lineTo(300, 20);
path.lineTo(200, 10);
path.lineTo(100, 70);
path.lineTo(50, 40);
path.close();
canvas.drawPath(path,mPaint);
9)繪制文字:
canvas.drawText("最喜歡看曹神日狗了~",50,50,mPaint); //繪制文字
你也可以沿著某條Path來繪制這些文字:
Path path = new Path();
path.moveTo(50,50);
path.lineTo(100, 100);
path.lineTo(200, 200);
path.lineTo(300, 300);
path.close();
canvas.drawTextOnPath("最喜歡看曹神日狗了~", path, 50, 50, mPaint); //繪制文字
10)繪制自定義的圖形:
代碼來源于網上:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(canvas.getWidth()/2, 200); //將位置移動畫紙的坐標點:150,150
canvas.drawCircle(0, 0, 100, mPaint); //畫圓圈
//使用path繪制路徑文字
canvas.save();
canvas.translate(-75, -75);
Path path = new Path();
path.addArc(new RectF(0,0,150,150), -180, 180);
Paint citePaint = new Paint(mPaint);
citePaint.setTextSize(14);
citePaint.setStrokeWidth(1);
canvas.drawTextOnPath("繪制表盤~", path, 28, 0, citePaint);
canvas.restore();
Paint tmpPaint = new Paint(mPaint); //小刻度畫筆對象
tmpPaint.setStrokeWidth(1);
float y=100;
int count = 60; //總刻度數
for(int i=0 ; i <count ; i++){
if(i%5 == 0){
canvas.drawLine(0f, y, 0, y+12f, mPaint);
canvas.drawText(String.valueOf(i/5+1), -4f, y+25f, tmpPaint);
}else{
canvas.drawLine(0f, y, 0f, y +5f, tmpPaint);
}
canvas.rotate(360/count,0f,0f); //旋轉畫紙
}
//繪制指針
tmpPaint.setColor(Color.GRAY);
tmpPaint.setStrokeWidth(4);
canvas.drawCircle(0, 0, 7, tmpPaint);
tmpPaint.setStyle(Paint.Style.FILL);
tmpPaint.setColor(Color.YELLOW);
canvas.drawCircle(0, 0, 5, tmpPaint);
canvas.drawLine(0, 10, 0, -65, mPaint);
}
本節小結:
本節我們對android.graphics接口類下的三個繪圖API:Canvas(畫布),Paint(畫筆),Path(路徑)進行 了學習,方法有很多,別去死記,用到的時候查就好,這里我們先有個大概映像即可,自定義控件那里 我們再來慢慢糾結~好的,就說這么多
UI組件化對項目有正向收益,不僅能提效,還能保證高度的視覺還原度,減少和UI設計師溝通成本,所以也得到了大家的認可。
所以每個項目都會啟動UI組件化建設,但是UI視圖是和項目強相關的,項目間無法復用,導致大家疲于實現,重復造輪子,拖延下班時間,那么基于上面的背景,有沒有更好的解決方案呢,答案是有的,下面介紹一下UI組件化在項目中的實施經驗,下面分為目標、工程架構、組件架構、組件實現來展開。
對現有UI組件化進行容器化抽象,底層UI組件提供最大功能集合,完全解耦業務邏輯,業務方根據自己需求,基于基礎組件開發,通過屬性配置或者組合的方式達到復雜的效果,所以只要底層組件抽象的足夠好、能力足夠全,就能大大的提高開發效率,后期適配也不會涉及核心邏輯修改,一定程度的保證了功能的穩定性
所有的ui組件統一收斂到uikit下,其下面moudle劃分以是否非常通用為依據,如果非業務屬性,并且特別通用的模塊組件,抽取單獨module,方便解耦和復用,如果不是則統一放在同一個module下,這樣uikit模塊劃分如下:
空殼工程,可以單獨運行
對所有的組件提供demo,里面的功能也可以在調試面板中打開
依賴widget和module,業務使用ui組件直接依賴uikit即可
工程架構可以分為5層,分別是:基礎控件、組合控件、業務UI組件、橋接、demo。
架構分層如下圖:
一個好的架構應該層次分明、低耦合、高擴展,對組件的增刪支持的足夠友好,任何組件都能準確的找到對應的分層,并且不會改動到已有代碼,所以review一下剛剛設計的架構,基本上滿足需求,架構設計符合預期。
架構設計好之后的步驟就是實施了,如何和現有的工程做結合呢,UI組件按階段可以分為:開發階段、穩定階段,理想的開發模式為開發階段在宿主工程中開發調試,但是放宿主工程中會帶了編譯慢的問題,組件開發和業務是接耦的,所以希望代碼在宿主工程,demo和組件開發可以單獨運行,當組件開發完成,到了穩定階段,組件代碼修改頻率降低,同時加快編譯速度,UIKit組件發布到遠程maven倉庫,最終uikit工程獨立出來,單獨迭代,下面是工程架構實現
UI組件和宿主打包編譯
settings.gradle
includeIfAbsent ':uikit:uikit'
includeIfAbsent ':uikit:demo'
includeIfAbsent ':uikit:imgselector'
includeIfAbsent ':uikit:roundview'
includeIfAbsent ':uikit:widget'
includeIfAbsent ':uikit:photodraweeview'
includeIfAbsent ':uikit:flatbutton'
includeIfAbsent ':uikit:dialog'
includeIfAbsent ':uikit:widgetlayout'
includeIfAbsent ':uikit:statusbar'
includeIfAbsent ':uikit:toolbar'
復制代碼
common_business.gradle中一鍵依賴
apply from: rootProject.file("library_base.gradle")
dependencies {
...
implementation project(":uikit:uikit")
}
復制代碼
UI組件獨立編譯
uikit/shell/settings.gradle
include ':app'
includeModule('widget','../')
includeModule('demo','../')
includeModule('flatbutton','../')
includeModule('imgselector','../')
includeModule('photodraweeview','../')
includeModule('roundview','../')
includeModule('uikit','../')
includeModule('widgetlayout','../')
includeModule('dialog','../')
includeModule('statusbar','../')
includeModule('toolbar','../')
def includeModule(name, filePath = name) {
def projectDir = new File(filePath+name)
if (projectDir.exists()) {
include ':uikit:' + name
project(':uikit:' + name).projectDir = projectDir
} else {
print("settings:could not find module $name in path $filePath")
}
}
復制代碼
UI組件lib的build.gradle中
if (rootProject.ext.is_in_uikit_project) {
apply from: rootProject.file('../uikit.gradle')
} else {
apply from: rootProject.file('uikit/uikit.gradle')
}
復制代碼
這樣就實現了宿主工程UIKit代碼單獨運行的效果了
組件可以分為2類:工具型、業務類型,2個類型的組件迭代思路差異非常的大,工具型組件,只要單點做到極致就ok了,整體比較簡單,復用性也比較強,而業務型組件就會稍顯復雜,既要考慮復用性,也要考慮可擴展性,下面分別介紹這2個類型組件的實現思路
工具型組件迭代的思路就是不斷的完善基礎能力,盡可能的功能全面,在已有的能力上不斷的支持新的功能,比較重要的就是兼容已有api,比較代表性的組件有FlatButton、RoundView、StatusBar,可以參考下FlatButton&RoundView迭代歷程:
如何做好一個業務組件呢,實現可以是具象的,也可以是抽象的,好的組件設計應該是2者兼備,最底層的實現應該是足夠抽象,而上層實現又應該是具象的,所以需要帶著容器化的思路來實現,那么怎么個思路呢,如下圖:
下面以FlatButton為例介紹組件實現方式,其它組件實現思路類似。在實現前,我們先看下視覺稿
按鈕樣式特別多,實現方式也可以有很多種,現有工程也給出了實現方案,具體如下:
第一步:分別定義noraml下的shape和pressed的shape,如果enable = false,還得再定義一個dissable的shape
normal (ui_standard_bg_btn_corner_28_ripple)
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/button_pressed_cover">
<item
android:drawable="@drawable/ui_standard_bg_btn_corner_28_enable">
</item>
</ripple>
復制代碼
pressed(ui_standard_bg_btn_corner_28_disable)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="@color/button_disable_end"
android:startColor="@color/button_disable_start"
android:useLevel="false"
android:type="linear" />
<corners android:radius="28dp" />
</shape>
復制代碼
第二步:定義selector
selector(ui_standard_bg_btn_corner_28)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/ui_standard_bg_btn_corner_28_ripple" />
<item android:state_enabled="false" android:drawable="@drawable/ui_standard_bg_btn_corner_28_disable" />
</selector>
復制代碼
第三步:使用
<TextView
...
android:background="@drawable/ui_standard_bg_btn_corner_28"
android:textColor="@color/white"/>
復制代碼
這樣按鈕的背景按壓就實現了,如果在此基礎上,文字也需要按壓態,那么就重復上面的步驟,對顏色再創建一個選擇器,當實現完上面UI定義的樣式后,工程中的畫風如下:
我是誰,我在哪里,這該怎么玩,長得都差不多,基本沒有開發體驗,復用性、擴展性都非常的差,如果來個UI大改版,又得從頭再來一次。那怎么解決上面的問題呢,答案是定義按鈕通用能力,業務上層再實現,按這個思路做,需要刪除上面所有shape、selector,然后自定義控件,我們都知道,上面定義的shape、selector xml文件,android系統最終都是會解析生成對應的對象,所以我們借鑒一下系統代碼,實現起來就so easy
看下這個shape xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="@color/button_disable_end"
android:startColor="@color/button_disable_start"
android:useLevel="false"
android:type="linear" />
<corners android:radius="28dp" />
</shape>
復制代碼
解析后的對象為GradientDrawable
public void setOrientation(Orientation orientation)
public void setColors(@Nullable @ColorInt int[] colors)
public void setCornerRadii(@Nullable float[] radii)
public void setStroke(int width, @ColorInt int color)
...
復制代碼
也就是說,xml中定義的屬性,代碼中都可以實現,除了GradientDrawable,還會用到RippleDrawable實現水波紋,同理文字顏色選擇器代碼中對應的為ColorStateList,有了上面鋪墊,具體實現如下:
<declare-styleable name="FlatButton">
<!--默認背景顏色 -->
<attr name="fb_colorNormal" format="color" />
<!--按下背景顏色 -->
<attr name="fb_colorPressed" format="color" />
<!--Disable背景顏色 -->
<attr name="fb_colorDisable" format="color" />
<!--默認開始漸變顏色 -->
<attr name="fb_colorNormalStart" format="color" />
<!--默認結束漸變顏色 -->
<attr name="fb_colorNormalEnd" format="color" />
<!--按下開始漸變顏色 -->
<attr name="fb_colorPressedStart" format="color" />
<!--按下結束漸變顏色 -->
<attr name="fb_colorPressedEnd" format="color" />
<!--Disable開始漸變顏色 -->
<attr name="fb_colorDisableStart" format="color" />
<!--Disable結束漸變顏色 -->
<attr name="fb_colorDisableEnd" format="color" />
<!--漸變方向 -->
<attr name="fb_gradientOrientation">
<enum name="left_right" value="0" />
<enum name="right_left" value="1" />
<enum name="top_bottom" value="2" />
<enum name="bottom_top" value="3" />
<enum name="tr_bl" value="4" />
<enum name="bl_tr" value="5" />
<enum name="br_tl" value="6" />
<enum name="tl_br" value="7" />
</attr>
<!--默認文字顏色 -->
<attr name="fb_colorNormalText" format="color" />
<!--按下文字顏色 -->
<attr name="fb_colorPressedText" format="color" />
<!--Disable文字顏色 -->
<attr name="fb_colorDisableText" format="color" />
<!--邊框顏色 -->
<attr name="fb_strokeColor" format="color" />
<!--按下邊框顏色 -->
<attr name="fb_strokePressColor" format="color" />
<!--Disable邊框顏色 -->
<attr name="fb_strokeDisableColor" format="color" />
<!--邊框寬度 -->
<attr name="fb_strokeWidth" format="dimension" />
<!--水波紋是否可用 -->
<attr name="fb_isRippleEnable" format="boolean" />
<!--默認水波紋顏色 -->
<attr name="fb_colorRippleNormal" format="color" />
<!--按下水波紋顏色 -->
<attr name="fb_colorRipplePressed" format="color" />
<!--圓角角度 -->
<attr name="fb_cornerRadius" format="dimension" />
<!--左上圓角角度 -->
<attr name="fb_radius_TL" format="dimension" />
<!--右上圓角角度 -->
<attr name="fb_radius_TR" format="dimension" />
<!--左下圓角角度 -->
<attr name="fb_radius_BL" format="dimension" />
<!--右下圓角角度 -->
<attr name="fb_radius_BR" format="dimension" />
<!--是否開啟防抖 -->
<attr name="fb_antiShakeEnable" format="boolean" />
</declare-styleable>
復制代碼
private fun setBackgroundCompat() {
val stateListDrawable = createStateListDrawable()
val pL = paddingLeft
val pT = paddingTop
val pR = paddingRight
val pB = paddingBottom
background = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && isRippleEnable) {
val rippleDrawable = RippleDrawable(createRippleColorStateList(), stateListDrawable, null)
rippleDrawable
} else {
stateListDrawable
}
setPadding(pL, pT, pR, pB)
}
private fun createStateListDrawable(): StateListDrawable {
var normalDrawable = StateListDrawable()
normalDrawable.addState(
intArrayOf(android.R.attr.state_pressed),
createPressedDrawable()
)
normalDrawable.addState(
intArrayOf(android.R.attr.state_focused),
createPressedDrawable()
)
normalDrawable.addState(
intArrayOf(-android.R.attr.state_enabled),
createDisableDrawable()
)
normalDrawable.addState(
intArrayOf(android.R.attr.state_selected),
createPressedDrawable()
)
normalDrawable.addState(intArrayOf(), createNormalDrawable())
return normalDrawable
}
private fun createRippleColorStateList(): ColorStateList {
val stateList = arrayOf(intArrayOf(android.R.attr.state_pressed), intArrayOf(android.R.attr.state_focused), intArrayOf(android.R.attr.state_activated), intArrayOf())
val normalColor = backgroundStyle.getColorRippleNormalFallback()
val pressedColor = backgroundStyle.getColorRipplePressedFallback()
val stateColorList = intArrayOf(
pressedColor,
pressedColor,
pressedColor,
normalColor
)
return ColorStateList(stateList, stateColorList)
}
復制代碼
xml中使用
<com.snapsolve.uikit.flatbutton.FlatButton
app:fb_colorNormalText="@color/uikit_color_white"
app:fb_colorPressedText="@color/uikit_color_white"
app:fb_colorNormalEnd="#FF9800"
app:fb_colorNormalStart="#FF0000"
app:fb_colorPressedEnd="#4CAF50"
app:fb_colorPressedStart="#009688"
app:fb_colorRippleNormal="#303F9F"
app:fb_colorRipplePressed="#FF4081"
app:fb_cornerRadius="24dp"
app:fb_gradientOrientation="left_right"
app:fb_isRippleEnable="true"
...
/>
復制代碼
代碼中使用
fb_radius_in_code.setBackgroundStyle {
this.colorNormal = resources.getColor(R.color.uikit_color_FF4081)
this.colorPressed = resources.getColor(R.color.uikit_color_9C27B0)
this.colorRippleNormal = resources.getColor(R.color.uikit_color_FF4081)
this.colorRipplePressed = resources.getColor(R.color.uikit_color_9C27B0)
}.setRadiusStyle {
this.radiusTL = dp2px(24F)
this.radius_BR = dp2px(24F)
}
復制代碼
到這里,底層Button能力定義完成,接下來就是組件化實現了,具體實現方式如下:
無法復制加載中的內容
項目中的按鈕UI按照UI組件要求,可以基于FlatButton來實現,配置好給種類型的屬性,按鈕名字可以和設計對齊,到這里就基本完成了
一級按鈕、二級按鈕、三級按鈕的實現可以通過繼承FlatButton,設置默認樣式,使用的時候就不需要再在xml中定義任何屬性,只需記住組件名字,依賴即可,做到真正的開箱即用
舉一個例子,定義一個線框button
class StrokeButton : FlatButton {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
config(context, attrs)
}
private fun config(context: Context, attrs: AttributeSet?){
.setBackgroundStyle {
this.colorNormal = resources.getColor(R.color.uikit_color_FF4081)
this.colorPressed = resources.getColor(R.color.uikit_color_9C27B0)
this.colorRippleNormal = resources.getColor(R.color.uikit_color_FF4081)
this.colorRipplePressed = resources.getColor(R.color.uikit_color_9C27B0)
}.setRadiusStyle {
this.radiusTL = dp2px(28F)
this.radius_BR = dp2px(28F)
}
}
private fun dp2px(dp: Float): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics)
}
}
復制代碼
業務使用
.相關方法詳解
1)Paint(畫筆):
就是畫筆,用于設置繪制風格,如:線寬(筆觸粗細),顏色,透明度和填充風格等 直接使用無參構造方法就可以創建Paint實例: Paint paint = new Paint( );
我們可以通過下述方法來設置Paint(畫筆)的相關屬性,另外,關于這個屬性有兩種, 圖形繪制相關與文本繪制相關:
2)Canvas(畫布):
畫筆有了,接著就到畫布(Canvas),總不能憑空作畫是吧~常用方法如下:
首先是構造方法,Canvas的構造方法有兩種:
Canvas(): 創建一個空的畫布,可以使用setBitmap()方法來設置繪制具體的畫布。
Canvas(Bitmap bitmap): 以bitmap對象創建一個畫布,將內容都繪制在bitmap上,因此bitmap不得為null。
接著是 1.drawXXX()方法族:以一定的坐標值在當前畫圖區域畫圖,另外圖層會疊加, 即后面繪畫的圖層會覆蓋前面繪畫的圖層。 比如:
2.clipXXX()方法族:在當前的畫圖區域裁剪(clip)出一個新的畫圖區域,這個畫圖區域就是canvas 對象的當前畫圖區域了。比如:clipRect(new Rect()),那么該矩形區域就是canvas的當前畫圖區域
3.save()和restore()方法: save( ):用來保存Canvas的狀態。save之后,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作! restore():用來恢復Canvas之前保存的狀態。防止save后對Canvas執行的操作對后續的繪制有影響。 save()和restore()要配對使用(restore可以比save少,但不能多),若restore調用次數比save多,會報錯!
4.translate(float dx, float dy): 平移,將畫布的坐標原點向左右方向移動x,向上下方向移動y.canvas的默認位置是在(0,0)
5.scale(float sx, float sy):擴大,x為水平方向的放大倍數,y為豎直方向的放大倍數
6.rotate(float degrees):旋轉,angle指旋轉的角度,順時針旋轉
3)Path(路徑)
簡單點說就是描點,連線~在創建好我們的Path路徑后,可以調用Canvas的drawPath(path,paint) 將圖形繪制出來~常用方法如下:
更高級的效果可以使用PathEffect類!
幾個To:
2.動手試試:
屬性那么多,肯定要手把手的擼一下,才能加深我們的映像是吧~ 嘿嘿,畫圖要么在View上畫,要么在SurfaceView上畫,這里我們在View上畫吧, 我們定義一個View類,然后再onDraw()里完成繪制工作!
/**
* Created by Jay on 2015/10/15 0015.
*/
public class MyView extends View{
private Paint mPaint;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true); //抗鋸齒
mPaint.setColor(getResources().getColor(R.color.puple));//畫筆顏色
mPaint.setStyle(Paint.Style.FILL); //畫筆風格
mPaint.setTextSize(36); //繪制文字大小,單位px
mPaint.setStrokeWidth(5); //畫筆粗細
}
//重寫該方法,在這里繪圖
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
然后布局那里設置下這個View就好,下述代碼都寫在onDrawable中~
1)設置畫布顏色:
canvas.drawColor(getResources().getColor(R.color.yellow)); //設置畫布背景顏色
2)繪制圓形:
canvas.drawCircle(200, 200, 100, mPaint); //畫實心圓
3)繪制矩形:
canvas.drawRect(0, 0, 200, 100, mPaint); //畫矩形
4)繪制Bitmap:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher), 0, 0, mPaint);
5)繪制弧形區域:
canvas.drawArc(new RectF(0, 0, 100, 100),0,90,true,mPaint); //繪制弧形區域
假如true改為false:
6)繪制圓角矩形
canvas.drawRoundRect(new RectF(10,10,210,110),15,15,mPaint); //畫圓角矩形
7)繪制橢圓
canvas.drawOval(new RectF(0,0,200,300),mPaint); //畫橢圓
8)繪制多邊形:
Path path = new Path();
path.moveTo(10, 10); //移動到 坐標10,10
path.lineTo(100, 50);
path.lineTo(200,40);
path.lineTo(300, 20);
path.lineTo(200, 10);
path.lineTo(100, 70);
path.lineTo(50, 40);
path.close();
canvas.drawPath(path,mPaint);
9)繪制文字:
canvas.drawText("最喜歡看曹神日狗了~",50,50,mPaint); //繪制文字
你也可以沿著某條Path來繪制這些文字:
Path path = new Path();
path.moveTo(50,50);
path.lineTo(100, 100);
path.lineTo(200, 200);
path.lineTo(300, 300);
path.close();
canvas.drawTextOnPath("最喜歡看曹神日狗了~", path, 50, 50, mPaint); //繪制文字
10)繪制自定義的圖形:
代碼來源于網上:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(canvas.getWidth()/2, 200); //將位置移動畫紙的坐標點:150,150
canvas.drawCircle(0, 0, 100, mPaint); //畫圓圈
//使用path繪制路徑文字
canvas.save();
canvas.translate(-75, -75);
Path path = new Path();
path.addArc(new RectF(0,0,150,150), -180, 180);
Paint citePaint = new Paint(mPaint);
citePaint.setTextSize(14);
citePaint.setStrokeWidth(1);
canvas.drawTextOnPath("繪制表盤~", path, 28, 0, citePaint);
canvas.restore();
Paint tmpPaint = new Paint(mPaint); //小刻度畫筆對象
tmpPaint.setStrokeWidth(1);
float y=100;
int count = 60; //總刻度數
for(int i=0 ; i <count ; i++){
if(i%5 == 0){
canvas.drawLine(0f, y, 0, y+12f, mPaint);
canvas.drawText(String.valueOf(i/5+1), -4f, y+25f, tmpPaint);
}else{
canvas.drawLine(0f, y, 0f, y +5f, tmpPaint);
}
canvas.rotate(360/count,0f,0f); //旋轉畫紙
}
//繪制指針
tmpPaint.setColor(Color.GRAY);
tmpPaint.setStrokeWidth(4);
canvas.drawCircle(0, 0, 7, tmpPaint);
tmpPaint.setStyle(Paint.Style.FILL);
tmpPaint.setColor(Color.YELLOW);
canvas.drawCircle(0, 0, 5, tmpPaint);
canvas.drawLine(0, 10, 0, -65, mPaint);
}
本節小結:
本節我們對android.graphics接口類下的三個繪圖API:Canvas(畫布),Paint(畫筆),Path(路徑)進行 了學習,方法有很多,別去死記,用到的時候查就好,這里我們先有個大概映像即可,自定義控件那里 我們再來慢慢糾結~好的,就說這么多
*請認真填寫需求信息,我們會在24小時內與您取得聯系。