Android自定義View實(shí)現(xiàn)LayoutParams的方法詳解
這一期我們來講一講LayoutParams這個(gè)玩意兒。Android入門的第一行代碼就牽扯到這個(gè)東西,然而,你真的理解夠了嗎?
第一層理解
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</RelativeLayout>layout_width和layout_height這個(gè)是不是最開始學(xué)的時(shí)候,就要搞清楚的基礎(chǔ)知識(shí),match_parent代表填充屏幕,wrap_content代表包裹內(nèi)容。這些其實(shí)是系統(tǒng)控件定義的屬性,通過TypedArray進(jìn)行解析。
第二層理解
val lp = RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT) lp.addRule(RelativeLayout.CENTER_VERTICAL) lp.addRule(RelativeLayout.BELOW, viewId) lp.setMargins(10, 20, 10, 20)
使用代碼動(dòng)態(tài)布局的時(shí)候設(shè)置LayoutParams。
第三層理解
好了,知識(shí)是在不斷打破舊的認(rèn)識(shí)中進(jìn)步的,第一層實(shí)際還沒到LayoutParams,還只是AttributeSet。系統(tǒng)何時(shí)將布局中的AttributeSet解析成LayoutParams的呢?
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new RelativeLayout.LayoutParams(getContext(), attrs);
}
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}ViewGroup有個(gè)關(guān)鍵的方法,generateLayoutParams()。
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.RelativeLayout_Layout);
final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion;
mIsRtlCompatibilityMode = (targetSdkVersion < JELLY_BEAN_MR1 ||
!c.getApplicationInfo().hasRtlSupport());
final int[] rules = mRules;
//noinspection MismatchedReadAndWriteOfArray
final int[] initialRules = mInitialRules;
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignWithParentIfMissing:
alignWithParent = a.getBoolean(attr, false);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toLeftOf:
rules[LEFT_OF] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toRightOf:
rules[RIGHT_OF] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_above:
rules[ABOVE] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_below:
rules[BELOW] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBaseline:
rules[ALIGN_BASELINE] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignLeft:
rules[ALIGN_LEFT] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignTop:
rules[ALIGN_TOP] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignRight:
rules[ALIGN_RIGHT] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignBottom:
rules[ALIGN_BOTTOM] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentLeft:
rules[ALIGN_PARENT_LEFT] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentTop:
rules[ALIGN_PARENT_TOP] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentRight:
rules[ALIGN_PARENT_RIGHT] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentBottom:
rules[ALIGN_PARENT_BOTTOM] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerInParent:
rules[CENTER_IN_PARENT] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerHorizontal:
rules[CENTER_HORIZONTAL] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_centerVertical:
rules[CENTER_VERTICAL] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toStartOf:
rules[START_OF] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_toEndOf:
rules[END_OF] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignStart:
rules[ALIGN_START] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignEnd:
rules[ALIGN_END] = a.getResourceId(attr, 0);
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentStart:
rules[ALIGN_PARENT_START] = a.getBoolean(attr, false) ? TRUE : 0;
break;
case com.android.internal.R.styleable.RelativeLayout_Layout_layout_alignParentEnd:
rules[ALIGN_PARENT_END] = a.getBoolean(attr, false) ? TRUE : 0;
break;
}
}
mRulesChanged = true;
System.arraycopy(rules, LEFT_OF, initialRules, LEFT_OF, VERB_COUNT);
a.recycle();
}這個(gè)代碼熟悉吧,這就是我們之前講過的自定義屬性??!沒錯(cuò),xml布局中的屬性會(huì)先被解析成LayoutParams。那么我問你個(gè)問題,你覺得generateLayoutParams()和generateDefaultLayoutParams()的這個(gè)LayoutParams是給自己用的呢?還是給它的子控件用的呢?它是給子控件用的。自己的那個(gè)直接在構(gòu)造方法中就從AttributeSet解析出來了。這樣你就理解了,為什么RelativeLayout的那些個(gè)
android:layout_centerVertical="true" android:layout_alignParentEnd="true"
怎么全部定義在子控件里面了。然后ViewGroup的addView()方法中就可以帶上這個(gè)LayoutParams了。
/**
* Adds a child view. If no layout parameters are already set on the child, the
* default parameters for this ViewGroup are set on the child.
*
* <p><strong>Note:</strong> do not invoke this method from
* {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},
* {@link #dispatchDraw(android.graphics.Canvas)} or any related method.</p>
*
* @param child the child view to add
* @param index the position at which to add the child
*
* @see #generateDefaultLayoutParams()
*/
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException(
"generateDefaultLayoutParams() cannot return null ");
}
}
addView(child, index, params);
}你不重寫generateLayoutParams()方法,怎么在添加子控件的時(shí)候,讓子控件用你的LayoutParams呢?
public static class LayoutParams extends ViewGroup.MarginLayoutParams {
}以上是LinearLayout.LayoutParams的摘要,我們自定義ViewGroup的時(shí)候,是不是也可以繼承個(gè)ViewGroup的LayoutParams玩一玩呢?然后重寫generateLayoutParams()和generateDefaultLayoutParams()方法。
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LinearLayout.LayoutParams(getContext(), attrs);
}這里return你的ViewGroup的LayoutParams,然后在你的ViewGroup的LayoutParams的構(gòu)造方法中就可以解析自定義屬性attrs了。如果忘記了解析方式,我給你個(gè)提示,使用context的obtainStyledAttributes()方法。
大部分停留在第二層理解,你如果學(xué)會(huì)了第三層,那么你自定義View又可以玩出新的高度了。
到此這篇關(guān)于Android自定義View實(shí)現(xiàn)LayoutParams的方法詳解的文章就介紹到這了,更多相關(guān)Android LayoutParams內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android使用ViewStub實(shí)現(xiàn)布局優(yōu)化方法示例
這篇文章主要為大家介紹了Android使用ViewStub實(shí)現(xiàn)布局優(yōu)化方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android頁面之間進(jìn)行數(shù)據(jù)回傳的方法分析
這篇文章主要介紹了Android頁面之間進(jìn)行數(shù)據(jù)回傳的方法,結(jié)合實(shí)例形式分析了Android頁面之間進(jìn)行數(shù)據(jù)的傳遞與處理技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
Android-實(shí)現(xiàn)切換Fragment頁功能的實(shí)現(xiàn)代碼
本篇文章主要介紹了Android-實(shí)現(xiàn)切換Fragment頁功能的實(shí)現(xiàn)代碼,具有一定的參加價(jià)值,有興趣的可以了解一下。2017-02-02
Android RecyclerView的Item自定義動(dòng)畫及DefaultItemAnimator源碼分析
這篇文章主要介紹了Android RecyclerView的Item自定義動(dòng)畫及DefaultItemAnimator源碼,感興趣的小伙伴們可以參考一下2016-07-07
Android UI設(shè)計(jì)系列之自定義EditText實(shí)現(xiàn)帶清除功能的輸入框(3)
這篇文章主要介紹了Android UI設(shè)計(jì)系列之自定義EditText實(shí)現(xiàn)帶清除功能的輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
Android中ScrollView監(jiān)聽滑動(dòng)距離案例講解
這篇文章主要介紹了Android中ScrollView監(jiān)聽滑動(dòng)距離案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Android點(diǎn)擊WebView實(shí)現(xiàn)圖片縮放及滑動(dòng)瀏覽效果
這篇文章主要為大家詳細(xì)介紹了Android點(diǎn)擊WebView實(shí)現(xiàn)圖片縮放及滑動(dòng)瀏覽效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
使用android隱藏api實(shí)現(xiàn)亮度調(diào)節(jié)的方法
使用android隱藏api實(shí)現(xiàn)亮度調(diào)節(jié)的方法,需要的朋友可以參考一下2013-05-05

