『壹』 android 自定義控制項開發,如何獲取子控制項的margin的值(大神請進……)
先通過getChildAt(int index)獲取到子控制項,再通過lp = getLayoutParams()獲取到子控制項的參數,lp.leftMargin就是你想要的數值
『貳』 Android如何在java代碼中設置margin
在xml里設置margin,如:<ImageView android:layout_margin="5dip" android:src="@drawable/image" />但是有些情況下,需要在java代碼里來寫,通過查閱android api,android.view.ViewGroup.MarginLayoutParams有個方法setMargins(left, top, right, bottom). 其直接的子類有: FrameLayout.LayoutParams, LinearLayout.LayoutParams and RelativeLayout.LayoutParams.:LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);lp.setMargins(10, 20, 30, 40);imageView.setLayoutParams(lp);
『叄』 android 怎麼在代碼中獲取控制項的屬性值
如果是自定義的控制項可以用一下代碼TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyToggleBtn);// 由attrs 獲得 TypeArray,
如果是系統自帶的控制項,通常控制項點get會有對應的獲取屬性值的方法,如textView.getHeight,不過有些方法如margin,就要通過layoutparam去獲取設置
『肆』 Android的布局屬性中padding和margin的區別
本文將講述HTML和CSS的關鍵—盒子模型(Box model). 理解Box model的關鍵便是margin和padding屬性, 而正確理解這兩個屬性也是學慣用css布局的關鍵.
注:為什麼不翻譯margin和padding? 原因一, 在漢語中並沒有與之相對應的詞語; 原因二: 即使有這樣的詞語, 由於在編寫css代碼時, 必須使用margin和padding, 如果我們總用漢語詞語代替其來解釋的話, 到了實際應用時容易混淆margin和padding的概念.
如果有一點Html基礎的話, 就應該了解一些基本元素(Element), 如p, h1~h6, br, div, li, ul, img等. 如果將這些元素細分, 又可以分別歸為頂級(top-level)元素,塊級(block-level) 元素和內聯(inline)元素.
1. Block-level element: 指能夠獨立存在, 一般的塊級元素之間以換行(如一個段落結束後另起一行)分隔. 常用的塊級元素包括: p, h1~h6, div, ul等;
2. Inline element: 指依附其他塊級元素存在, 緊接於被聯元素之間顯示, 而不換行. 常用的內聯元素包括: img, span, li, br等;
3. Top-level element: 包括html, body, frameset, 表現如Block-level element, 屬於高級塊級元素.
塊級元素是構成一個html的主要和關鍵元素, 而任意一個塊級元素均可以用Box model來解釋說明.
Box Model:任意一個塊級元素均由content(內容), padding, background(包括背景顏色和圖片), border(邊框), margin五個部分組成. 立體圖如下(Fig. 1):
即ab=cd=30px, ID1的margin-top/bottom=10px被折疊了, 而且ID1應有的margin黑色背景也一同被折疊消失了.
為什麼會折疊:造成以上現象的原因是, 我們在css中並沒有聲明id為ID1的元素div的height(高), 因此它的高便被設為auto(自動)了. 一旦其值被設為auto, 那麼瀏覽器就會認為它的高為子元素ID2的border-top到border-bottom之間的距離, 即Fig. 4中bc的長度, 所以子元素ID2的margin-top/bottom(30px)就伸出到了父元素ID1之外, 出現了Fig. 4中ab與cd之間的空白區域. 因此父元素ID1的margin-top/bottom因子元素的」紅杏出牆」而被折疊消失了.
如何解決折疊問題:可能大家最初想到的辦法就是根據折疊發生的原因—auto, 來解決問題. 但是, 在實際操作中, 某些元素如div, h1, p等, 我們是不可能預先知道它的高是多少的, 因此在css文件中是不能常規通過聲明元素的高來解決折疊問題.
我們需要在css文件中加入如下代碼(紅色部分):
#ID1 {
background-color: #333;
color: #FFF;
margin-top: 10px;
margin-bottom: 10px;
padding-top:1px;
padding-bottom:1px;
}
或是:
#ID1 {
background-color: #333;
color: #FFF;
margin-top: 10px;
margin-bottom: 10px;
border-top:1px solid #333;
border-bottom:1px solid #333;
}
通過增加以上代碼, 便可使瀏覽器重新計算ID1的高, 使其為子元素ID2的margin-top/bottom外緣(outer top/bottom)之間的距離, 即Fig. 3中be的距離.
簡單說來:
也就是說 設置margin 那麼他所佔據的空白地方會是在邊框外面
設置padding 他所佔據的空白地方是在邊框裡面
而且在IE6 一下的版本中 存在這padding 計算錯誤的BUG
CSS 的寬度屬性本來是不包含padding的 但是 在ie下面有的時候寬度是包含padding 所以 建議在不熟悉CSS 在定位的時候 都用margin屬性
『伍』 Android自定義控制項總結
每個view的坐標系原點為左上角那個點,水平方向為x軸,右正左負,豎直方向為y軸,下正上負。
canvas.drawColor //繪制區域塗上顏色(設置底色/蒙層)
canvas.drawCircle(float centerX(圓心X坐標),float centerY(圓心Y坐標),float radius(圓的半徑,單位像素),Paint paint)
canvas.drawBitmap
canvas.drawRect(float left,float top,float right,float bottom,Paint paint) //畫矩形
canvas.drawRect(RecF rect,Paint paint)
canvas.drawRect(Rect rect,Paint paint)
canvas.drawPoint(float x(點X軸坐標),float y(點Y軸坐標),Paint paint)//畫點
點的大小 ->paint.setStrokeWidth(width)
點的形狀 ->paint.setStrokeCap(cap)
ROUND(圓形),BUTT(平頭),SQUARE(方頭)
canvas.drawPoints()//批量畫點
canvas.drawOval(float left(左邊界點),float top(上邊界點),float right(右邊界點),float bottom(下邊界點),Paint paint) //畫橢圓
canvas.drawLine(float startX(起點X軸坐標),float startY(起點Y軸坐標),float stopX(終點X軸坐標),float stopY(終點X軸坐標),Paint paint) (setStyle對直線沒有影響)
canvas.drawLines(批量畫線)
canvas.drawRoundRect(float left,float top,float right,float bottom,float rx(圓角的橫向半徑),float ry(圓角的縱向坐標),Paint paint)//畫圓角矩形
canvas.drawRoundRect(RectF rect,float rx, float ry,Paint paint)
canvas.drawArc(float left, float top, float right, float bottom, float startAngle(起始角度,順時針為正,逆時針為負), float sweepAngle(弧形劃過角度), boolean useCenter(是否連接到圓心), Paint paint) //繪制弧形或扇形 根據弧形所在橢圓進行繪制
canvas.drawPath() //通過描述路徑的方式來繪制圖形
path.addXxx() —添加子圖形
path.addCircle(x,y,radius,dir(路徑方向:順時針/逆時針))
path.xxxTo —畫線
path.lineTo()
path.rLineTo()
path.close() —封閉當前圖形
path.setFillType(Path.FillType ft) //設置填充模式
canvas.drawBitmap(Bitmap bitmap,float left,float top,Paint paint);//畫bitmap
canvas.drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint)
canvas.drawBitmap(Bitmap bitmap,Rect src,Rect dst,Paint paint)
canvas.drawBitmap(Bitmap bitmap,Matrix matrix,Paint paint)
canvas.drawText(String text,float x(起點x坐標),float y(起點y坐標),Paint paint) //繪制文字
Paint.setStyle //設置繪制模式
FILL 填充模式(默認)
STROKE 畫線模式
FILL_AND_STROKE 既畫線又填充
Paint.setStrokeWidth //設置線條寬度 (僅在style:Stroke、FILL_AND_STROLE下有效)
Paint.setTextSize //設置文字大小
Paint.setAntiAlias //設置抗鋸齒開關
Paint.setTextSize(float textSize)//設置文字大小
Paint.setStrokeJoin(Paint.Join join) //設置拐角的形狀
MITER//尖角(默認)
BEVEL//平角
ROUND//圓角
Paint.setStokeMiter(float miter)//設置MITER型拐角的延長線的最大值
設置顏色
直接設置顏色
Paint.setColor(int color)
Paint.setARGB(int a,int r,int g,int b)
Paint.setShader(Shader shader) //設置shader
LinearGradient 線性漸變
RadialGradient 輻射漸變
SweepGradient 掃描漸變
BitmapShader 用bitmap的像素來作為圖形或文字的填充
ComposeShader 混合著色器,多個shader混合使用
Paint.setColorFilter(ColorFilter colorFilter) //設置顏色過濾
Paint.setXfermode(Xfermode xfermode) //以要繪制的內容為源圖像,以View中已有內容作為目標圖像,選取一個PorterDuff.Mode作為繪制內容的顏色處理方案。
色彩優化
Paint.setDither(boolean dither) //設置抖動來優化色彩深度降低時的繪制效果
Paint.setFilterBitmap(boolean filter) //設置雙線性過濾優化Bitmap放大繪制的效果
可以理解為 由馬賽克變成模糊狀態
Paint.setPathEffect(PathEffect effect)//使用PathEffect設置形狀的輪廓效果
CornerPathEffect//把所有的拐角變成圓角
DiscretePathEffect//把線條進行隨機的偏離
DashPathEffect//使用虛線
PathDashPathEffect//使用一個Path來繪制虛線
SumPathEffect//組合效果
ComposePathEffect//組合效果,組合有先後順序
Paint.setShadowLayer(float radius,float dx,float dy,int shadowColor)//添加陰影
Paint.setMaskFilter(MaskFilter maskfilter)//在繪制層上方的附加效果
BlurMaskFilter //模糊效果
new BlurMaskFilter(float radius(模糊范圍),BlurMaskFilter.Blur style(模糊類型))
EmbossMaskFilter//浮雕效果
new EmbossMaskFilter(float[] direction(光源的方向),float ambient(環境光強度),float specular(炫光系數),float blurRadius(光線范圍))
獲取繪制的Path
getFillPath(Path src,Path dst)//實際path
getTextPath(Stirng text,int start,int end,float x,float y,Path)/getTextPath(char[] text,int index,int count,float x,float y,Path path)//文字的path
drawTextOnPath()//沿一條Path來繪制文字
StaticLayout //繪制文字,支持換行
paint.setFakeBoldText(booleab fakeBoldText)//是否使用偽粗體
paint.setStrikeThruText()//是否加刪除線
paint.setUnderLineText(boolean underlineText)//是否加下劃線
paint.setTextSkewX(float skewX)//設置文字橫向錯切角度
paint.setTextScaleX(float scaleX)//設置文字橫向放縮
paint.setLetterSpacing(float letterSpacing)//設置字元間距,默認為0
paint.setTextAlign(Paint.Align align)//LEFT、CENTER、RIGHT默認為LEFT
paint.setTextLocale(Locale locale)/paint.setTextLocales(LocaleList locales) //設置繪制所用的地域
paint.setHinting(int mode)//是否啟用字體微調
測量文字尺寸類:
paint.getFontSpacing();//獲取推薦的行距
paint.getFontMetrics();//獲取point的FontMetrics
baseline:基準線
ascent/descent:普通字元的頂部和底部范圍
top/bottom:限制字型的頂部和底部
leading:行的額外間距,即上一行字的bottm與下一行字的top距離
paint.getTextBounds(String text(測量的文字),int start(文字的起始位置),int end(文字的結束位置),Rect bounds(文字顯示範圍的對象))//獲取文字的顯示範圍
paint.measureText(String text)//測量文字佔用的寬度
measureText()>getTextBounds()
paint.getTextWidths(String text,float[] widths)//獲取字元串中每個字元的寬度,並把結果填入參數widths
paint.breakText(String text((要測量的文字),boolean measureForwards(測量的方向),float maxWidth(寬度上限(超出上限會截斷文字)),float[] measuredWidth(用於接受數據))//測量完成後會把文字寬度賦給measureWidth[0]
paint.getRunAdvance(CharSequence text,int start(文字的起始坐標),int end(文字的結束坐標),int contextStart(上下文的起始坐標),int ContextEnd(上下文的結束坐標),boolean isRtl(文字的方向),int offset(字數的偏移))//計算某個字元處游標的x坐標
paint.getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)//計算出文字中最接近這個位置的字元偏移量
paint.hasGlyph(String s)//檢查指定的字元串是否是一個單獨的字型
canvas.clipRect()//范圍裁剪
canvas.clipPath()//根據范圍裁剪
canvas.translate(float dx,float dy)//位移
canvas.rotate(float degrees,float px,float py)//旋轉
canvas.scale(float sx(橫向縮放倍數),float sy(縱向縮放倍數),float px,float py)//縮放
canvas.skew(float sx(x軸的錯切系數),float sy(y軸的錯切系數))//錯切
canvas.setMatrix(matrix)//用Matrix直接替換Canvas當前的變換矩陣
canvas.concat(matrix)//用Canvas當前的變換矩陣和Matrix相乘
Camera.rotate*()//三維旋轉
1、super.draw()//總調度方法
2、super.onDraw()
3、dispatchDraw()//繪制子View的方法
繪制順序:
draw()總調度方法,view的繪制過程都發生在draw()方法里
1、背景(drawBackground()不能重寫)-------android:background:/View.setBackgroundXxx()
2、主體(onDraw())
3、子View(dispatchDraw())
4、滑動邊緣漸變和滑動條(onDrawForeground())-------android:scrollbarXxx/View.setXXXScrollBarXXX()
5、前景(onDrawForeground())-------android:foreground/View.setForeground()
view.animate().translationX()//x軸偏移
1、如果是自定義控制項,需要添加setter、getter方法
2、ObjectAnimator.ofXXX()創建ObjectAnimator對象
3、用start()方法執行動畫
setDuration(int ration)//設置動畫時長
setInterpolator(Interpolator interpolator)//設置插值器
ViewPropertyAnimator.setListener()/ObjectAnimator.addListener()
ViewPropertyAnimator.setUpdateListener()/ObjectAnimator.addUpdateListener()
ObjectAnimator.addPauseListener()
ViewPropertyAnimator.withStartAction/EndAction()
ArgbEvaluator//顏色漸變動畫
PropertyValuesHolder//同一個動畫中改變多個屬性
PropertyValuesHolders.ofKeyframe()//把同一個屬性拆分
AnimatorSet//多個動畫配合執行
targetSdkVersion>=14,硬體加速默認開啟
view.setLayerType()
LAYER_TYPE_SOFTWARE:使用軟體來繪制View Layer,繪制到Bitmap,並順便關閉硬體加速
LAYER_TYPE_HARDWARE:使用GPU來繪制View Layer,繪制到OpenGL texture(如果硬體加速關閉,那麼行為和LAYER_TYPE_SOFTWARE一致)
LAYER_TYPE_NONE:關閉View Layer
View Layer可以加速無invalidate()(例如動畫)時的刷新效率,但對於需要調用invalidate()的刷新無法加速
硬體加速並不支持所有的繪制操作
1、測量(measure)
View:View在onMeasuer中會計算自己的尺寸然後保存
ViewGroup:ViewGroup在onMeasure中會調用所有子View的measure讓它們進行自我測量,並根據子View
計算出的期望尺寸來計算他們的事跡尺寸和位置然後保存。
2、布局(layout)
View:無子View所以onLayout不做任何處理
ViewGroup:ViewGroup在onLayout中會調用自己所有子View的layout方法,把他們的尺寸、位置傳給他們, 讓他們完成自我布局。
MeasureSpec = mode + size :父類傳遞過來給當前View的一個建議值
MeasureSpec.getMode(int spec)//獲取模式
MeasureSpec.getSize(int spec)//獲取數值
限制分類:
UNSPECIFIED(不限制)
AT_MOST(限制上限)->wrap_content
EXACTLY(限制固定值)->match_parent/具體值
1、重寫onMeasure來修改已有的View尺寸
(1)、重寫onMeasure方法,調用super.onMeasure觸發原有的自我測量。
(2)、在super.onMeasure下用getMeasureWidth與getMeasureHeigh獲取之前測量的結果,使用自己的演算法計算新結果。
(3)、調用setMeasureDimension保存新結果。
2、重寫onMeasure來全新定製自定義View的尺寸
與1區別,保證計算的同時,保證結果滿足父View給出的尺寸限制
(1)重寫onMeasure,計算出View的尺寸
(2)使用resolve讓子View的計算結果符合父View的限制,也可不使用該方法自己定義
3、重寫onMeasure和onLayout來全新定製自定義ViewGroup的內部布局
兩個注意點:
子控制項間的margin值
1、重寫generateLayoutParams()和generateDefaultLayoutParams()
2、獲取margin值 MarginLayoutParams lp = (MarginLayoutParams )child.getLayoutParams()
子控制項間的padding值
1、測量後直接getPaddingLeft、getPaddingTop、getPaddingRight、getPaddingBottom
重寫onMeasure來計算內部布局
(1)調用每個子View的measure來計運算元View的尺寸
結合layout_xxx和自己可用空間
(2)計運算元View的位置並保存子View的尺寸和位置
(3)計算自己的尺寸並用setMeasureDimension保存
重寫onLayout來擺放子View
(1)調用每個子View的layout,讓他們保存自己的位置和尺寸
view工作原理
觸摸事件
1、ACTION_DOWN:手指剛接觸屏幕,按下去的那一瞬間
2、ACTION_MOVE:手指在屏幕上移動
3、ACTION_UP:手指從屏幕上松開的瞬間
事件序列:從ACTION_DOWN -> ACTION_UP
ViewGroup:
DispatchTouchEvent
• return true:表示該View內部消化掉了所有事件
• return false:表示事件在本層不再繼續進行分發,並交由上層控制項的onTouchEvent方法進行消費
• return super.dispatchTouchEvent(ev):默認事件將分發給本層的事件攔截onInterceptTouchEvent方法 進行處理
OnInterceptTouchEvent
• return true:表示將事件進行攔截,並將攔截到的事件交由本層控制項的onTouchEvent進行處理
• return false:表示不對事件進行攔截,事件得以成功分發到子View
• return super.onInterceptTouchEvent(ev):默認表示不攔截該事件,並將事件傳遞給下一層View的 dispatchTouchEvent
OnTouchEvent 默認false
• return true:表示onTouchEvent處理完事件後消費了此次事件
• return fasle:表示不響應事件,那麼該事件將會不斷向上層View的onTouchEvent方法傳遞,直到某個View的 onTouchEvent方法返回true
• return super.dispatchTouchEvent(ev):表示不響應事件,結果與return false一樣
子View不存在分發:
• DispatchTouchEvent 事件分發
• OnTouchEvent 默認true
如下圖為事件分發流程圖:
---------------------- 以上總結部分源自Hencoder教程 ------------------------------