最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義ViewGroup的實(shí)現(xiàn)方法

 更新時(shí)間:2016年05月25日 14:29:26   作者:summerpxy  
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下

     在android中提供了常見(jiàn)的幾種ViewGroup的實(shí)現(xiàn),包括LinearLayout、Relativeayout、FrameLayout等。這些ViewGroup可以滿(mǎn)足我們一般的開(kāi)發(fā)需求,但是對(duì)于界面要求復(fù)雜的,這幾個(gè)布局就顯得捉襟見(jiàn)肘了。所以自定義的ViewGroup在我們接觸過(guò)的應(yīng)用中比比皆是。

     要想實(shí)現(xiàn)一個(gè)自定義的ViewGroup,第一步是學(xué)會(huì)自定義屬性,這些自定義的屬性將讓我們配置布局文件的時(shí)候更加的靈活。自定義屬性是在value目錄下聲明一個(gè)attrs.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="CascadeViewGroup">
  <attr name="verticalspacing" format="dimension"/>
  <attr name="horizontalspacing" format="dimension"/>
 </declare-styleable>

 <declare-styleable name="CascadeViewGroup_LayoutParams">
  <attr name="layout_paddingleft" format="dimension"/>
  <attr name="layout_paddinTop" format="dimension"/>
 </declare-styleable>
</resources>

      在這里我們聲明了兩個(gè)自定義屬性集,CascadeViewGroup中的屬性是針對(duì)我們自定義的CascadeViewGroup組件設(shè)置的,也就是可以在布局文件中<CascadeViewGroup>標(biāo)簽中可以使用的屬性。另外一個(gè)CascadeViewGroup_LayoutParams則是針對(duì)于CascadeViewGroup中的子View設(shè)置的屬性。

    在編寫(xiě)代碼前,我們還設(shè)置了一個(gè)默認(rèn)的寬度和高度供CascadeLayout使用。這兩個(gè)屬性在dimens.xml定義。

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <dimen name="default_horizontal_spacing">10dp</dimen>
 <dimen name="default_vertical_spacing">10dp</dimen>
</resources>

下面開(kāi)始編寫(xiě)自定義的組件CascadeLayout了。

package com.app.CustomViewMotion;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by charles on 2015/8/13.
 */
public class CascadeViewGroup extends ViewGroup {

 //自定義布局中設(shè)置的寬度和高度
 private int mHoriztonalSpacing;
 private int mVerticalSpacing;

 public CascadeViewGroup(Context context) {
  this(context, null);
 }

 public CascadeViewGroup(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public CascadeViewGroup(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CascadeViewGroup);
  try {
   //獲取設(shè)置的寬度
   mHoriztonalSpacing = a.getDimensionPixelSize(R.styleable.CascadeViewGroup_horizontalspacing,
     this.getResources().getDimensionPixelSize(R.dimen.default_horizontal_spacing));
   //獲取設(shè)置的高度
   mVerticalSpacing = a.getDimensionPixelSize(R.styleable.CascadeViewGroup_verticalspacing,
     this.getResources().getDimensionPixelSize(R.dimen.default_vertical_spacing));

  } catch (Exception e) {
   e.printStackTrace();

  } finally {
   a.recycle();
  }
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  final int count = this.getChildCount();
  int width = this.getPaddingLeft();
  int height = this.getPaddingTop();
  for (int i = 0; i < count; i++) {
   final View currentView = this.getChildAt(i);
   this.measureChild(currentView, widthMeasureSpec, heightMeasureSpec);
   CascadeViewGroup.LayoutParams lp = (CascadeViewGroup.LayoutParams) currentView.getLayoutParams();
   if(lp.mSettingPaddingLeft != 0){
    width +=lp.mSettingPaddingLeft;
   }
   if(lp.mSettingPaddingTop != 0){
    height +=lp.mSettingPaddingTop;
   }
   lp.x = width;
   lp.y = height;
   width += mHoriztonalSpacing;
   height += mVerticalSpacing;
  }
  width +=getChildAt(this.getChildCount() - 1).getMeasuredWidth() + this.getPaddingRight();
  height += getChildAt(this.getChildCount() - 1).getMeasuredHeight() + this.getPaddingBottom();
  this.setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec));

 }

 @Override
 protected void onLayout(boolean b, int l, int i1, int i2, int i3) {
  final int count = this.getChildCount();
  for (int i = 0; i < count; i++) {
   final View currentView = this.getChildAt(i);
   CascadeViewGroup.LayoutParams lp = (CascadeViewGroup.LayoutParams) currentView.getLayoutParams();
   currentView.layout(lp.x, lp.y, lp.x + currentView.getMeasuredWidth(),
     lp.y + currentView.getMeasuredHeight());
  }


 }

 public static class LayoutParams extends ViewGroup.LayoutParams {
  int x;
  int y;
  int mSettingPaddingLeft;
  int mSettingPaddingTop;

  public LayoutParams(Context c, AttributeSet attrs) {
   super(c, attrs);
   TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.CascadeViewGroup_LayoutParams);
   mSettingPaddingLeft = a.getDimensionPixelSize(R.styleable.CascadeViewGroup_LayoutParams_layout_paddingleft, 0);
   mSettingPaddingTop = a.getDimensionPixelSize(R.styleable.CascadeViewGroup_LayoutParams_layout_paddinTop, 0);
   a.recycle();
  }

  public LayoutParams(int width, int height) {
   super(width, height);
  }

  public LayoutParams(ViewGroup.LayoutParams source) {
   super(source);
  }
 }

 @Override
 protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
  return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
 }

 @Override
 protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
  return new LayoutParams(p);
 }

 @Override
 public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
  return new LayoutParams(this.getContext(), attrs);
 }
}

代碼稍微優(yōu)點(diǎn)長(zhǎng),但是結(jié)構(gòu)還是很清晰的。

1)構(gòu)造方法中或者XML文件中配置屬性的值。通過(guò)TypedArray中的方法獲取我們?cè)趌ayout布局中設(shè)置的屬性,并且將他們保存在成員變量中。

2)構(gòu)造自定義的內(nèi)部類(lèi)LayoutParams。構(gòu)造這個(gè)內(nèi)部類(lèi),可以方便我們?cè)跍y(cè)量我們的子View的時(shí)候保存他們的屬性值,以便在Layout階段布局。

3)generateLayoutParams()、generateDefaultParams()等方法。在這些方法中返回我們自定義的layoutParams。至于為什么要重寫(xiě)這些方法,可以查看ViewGroup類(lèi)的addView()方法就很清楚了。

4)measure階段。在measure階段,我們會(huì)測(cè)量自己的大小,同時(shí)也要測(cè)量子View的大小,并且將子View的信息保存在LayoutParams中。

5)layout階段。根據(jù)各個(gè)子View的信息,布局他們的位置。

最后加上布局文件。

<?xml version="1.0" encoding="utf-8"?>
<!--添加自定義屬性給viewGroup-->
<!--新添加的命名空間的后綴必須保持和.xml中聲明的包名一致-->
<com.app.CustomViewMotion.CascadeViewGroup
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:ts="http://schemas.android.com/apk/res/com.app.CustomViewMotion"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  ts:horizontalspacing="15dp"
  ts:verticalspacing="15dp">

 <TextView android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="text1"
    android:background="#668B8B"/>

 <TextView android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="text2"
    android:background="#FFDAB9"/>

 <TextView android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="text3"
    android:background="#43CD80"/>

<!--這個(gè)子view中添加自定義子view屬性-->
 <TextView android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="text4"
    ts:layout_paddingleft="100dp"
    ts:layout_paddinTop="100dp"
    android:background="#00CED1"/>
</com.app.CustomViewMotion.CascadeViewGroup>



實(shí)現(xiàn)的效果如下:

以上就是的全部?jī)?nèi)容,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • RecyclerView消除底部分割線(xiàn)的方法

    RecyclerView消除底部分割線(xiàn)的方法

    這篇文章主要為大家詳細(xì)介紹了RecyclerView消除底部分割線(xiàn)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android畫(huà)板開(kāi)發(fā)之橡皮擦功能

    Android畫(huà)板開(kāi)發(fā)之橡皮擦功能

    這篇文章主要為大家詳細(xì)介紹了Android畫(huà)板開(kāi)發(fā)之橡皮擦功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • Android實(shí)現(xiàn)實(shí)時(shí)搜索框功能

    Android實(shí)現(xiàn)實(shí)時(shí)搜索框功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)實(shí)時(shí)搜索框功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Android設(shè)置TextView首行縮進(jìn)示例代碼

    Android設(shè)置TextView首行縮進(jìn)示例代碼

    使用過(guò)word的都會(huì)知道,在文字排版的時(shí)候經(jīng)常要設(shè)置首行縮進(jìn),這樣才會(huì)使排版更整齊,那么在Android中當(dāng)需要設(shè)置首行縮進(jìn)的時(shí)候該腫么辦呢,下面一起來(lái)看看。
    2016-08-08
  • Android應(yīng)用UI開(kāi)發(fā)中Fragment的常見(jiàn)用法小結(jié)

    Android應(yīng)用UI開(kāi)發(fā)中Fragment的常見(jiàn)用法小結(jié)

    這篇文章主要介紹了Android應(yīng)用UI開(kāi)發(fā)中Fragment的常見(jiàn)用法小結(jié),Fragment的存在是為了解決不同屏幕分辯率的動(dòng)態(tài)和靈活UI設(shè)計(jì),需要的朋友可以參考下
    2016-02-02
  • Flutter?Widget?之package?mason實(shí)現(xiàn)詳解

    Flutter?Widget?之package?mason實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了Flutter?Widget?之package:?mason實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 詳解App?;顚?shí)現(xiàn)原理

    詳解App?;顚?shí)現(xiàn)原理

    一直以來(lái),App 進(jìn)程保活都是各大廠商,特別是頭部應(yīng)用開(kāi)發(fā)商永恒的追求。畢竟App 進(jìn)程死了,就什么也干不了了;一旦 App 進(jìn)程死亡,那就再也無(wú)法在用戶(hù)的手機(jī)上開(kāi)展任何業(yè)務(wù),所有的商業(yè)模型在用戶(hù)側(cè)都沒(méi)有立足之地
    2021-06-06
  • 安卓圖片反復(fù)壓縮后為什么普遍會(huì)變綠而不是其它顏色?

    安卓圖片反復(fù)壓縮后為什么普遍會(huì)變綠而不是其它顏色?

    今天小編就為大家分享一篇關(guān)于安卓圖片反復(fù)壓縮后為什么普遍會(huì)變綠而不是其它顏色?,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Android仿微信錄音功能(錄音后的raw文件轉(zhuǎn)mp3文件)

    Android仿微信錄音功能(錄音后的raw文件轉(zhuǎn)mp3文件)

    這篇文章主要介紹了Android中仿微信錄音功能錄音后的raw文件轉(zhuǎn)mp3文件,本文通過(guò)實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2019-11-11
  • Android Intent調(diào)用 Uri的方法總結(jié)

    Android Intent調(diào)用 Uri的方法總結(jié)

    這篇文章主要介紹了Android Intent調(diào)用 Uri的方法總結(jié)的相關(guān)資料,這里整理了Android Intent 調(diào)用Uri的常用方法,需要的朋友可以參考下
    2017-09-09

最新評(píng)論

罗源县| 江津市| 阳春市| 江孜县| 肥西县| 柳州市| 潜江市| 南丹县| 岚皋县| 浪卡子县| 平阴县| 安龙县| 郴州市| 陇西县| 新和县| 延寿县| 碌曲县| 洛南县| 富平县| 元朗区| 大渡口区| 宁蒗| 安多县| 界首市| 阳泉市| 商城县| 探索| 邵阳市| 南昌市| 益阳市| 新郑市| 钦州市| 垦利县| 庆安县| 祁阳县| 沈丘县| 娄底市| 宽城| 湖南省| 闻喜县| 晋中市|