Heim > Java > javaLernprogramm > Zusammenfassung der Verwendung einer benutzerdefinierten ViewGroup in Android

Zusammenfassung der Verwendung einer benutzerdefinierten ViewGroup in Android

高洛峰
Freigeben: 2017-01-16 16:24:21
Original
1517 Leute haben es durchsucht

Kategorie

Benutzerdefiniertes Layout kann in zwei Situationen unterteilt werden.

Anpassen Sie ViewGroup und erstellen Sie einige ViewGroups, die sich von LinearLayout, RelativeLayout usw. unterscheiden. Zum Beispiel: GridLayout nach API 14 hinzugefügt, CoordinatorLayout in der Design-Support-Bibliothek usw.

Passen Sie einige vorhandene Layouts an und fügen Sie einige Sonderfunktionen hinzu. Zum Beispiel: TableLayout und PercentFrameLayout in Prozent unterstützen Bibliothek usw.

Prozess

Der Prozess der benutzerdefinierten Ansicht ist: onMeasure()->onLayout()->onDraw(). Beim Anpassen von ViewGroup ist es im Allgemeinen nicht erforderlich, onDraw zu implementieren. Natürlich können besondere Anforderungen gelten, wie zum Beispiel: CoordinatorLayout.

OnMeasure und onLayout können also grundsätzlich die meisten ViewGroups ausführen, mit denen wir in Kontakt kommen. Aber es reicht nicht aus, nur zu wissen, wie man die Größe der ViewGroup in onMeasure misst und die Position der Child View in onLayout berechnet.

Zum Beispiel: Wie können Sie Eigenschaften für die untergeordnete Ansicht einer ViewGroup festlegen?

Ein Beispiel.

Schreiben Sie eine benutzerdefinierte ViewGroup und fügen Sie ein Attribut hinzu, um die Größe (Länge und Breite) der untergeordneten Ansicht im Verhältnis zur ViewGroup zu steuern.

Angenommen, es handelt sich um ein LinearLayout, dann definieren Sie zuerst ein CustomLinearLayout.

public class CustomLinearLayout extends LinearLayout {
  public CustomLinearLayout(Context context) {
    super(context);
  }
 
  public CustomLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
 
  public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
 
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }
}
Nach dem Login kopieren

Abgesehen von anderen Dingen müssen wir Attribute hinzufügen, um die Größe der untergeordneten Ansicht zu steuern. Definieren Sie dann dieses Attribut zuerst in value/attr.xml (verwenden Sie CustomLinearLayout_Layout, um es von CustomLinearLayout zu unterscheiden, der Name ist natürlich willkürlich).

<declare-styleable name="CustomLinearLayout_Layout">
  <!-- 定义比例 -->
  <attr name="inner_percent" format="float"/>
</declare-styleable>
Nach dem Login kopieren

Diese Methode wird schließlich aufgerufen, wenn ViewGroup addView() aufruft.

public void addView(View child, int index, LayoutParams params)
Nach dem Login kopieren

Dieser Parameter stellt die Konfiguration von ViewGroup.LayoutParams dar, einschließlich Breite und Höhe, LinearLayout.LayoutParams fügt Gewichtsattribute usw. hinzu. Dann sollten wir ein LayoutParams implementieren. Das war's also vorerst.

public class CustomLinearLayout extends LinearLayout {
  public CustomLinearLayout(Context context) {
    super(context);
  }
 
  public CustomLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
 
  public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
 
  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
  }
  public static class LayoutParams extends LinearLayout.LayoutParams {
 
    private float innerPercent;
 
    private static final int DEFAULT_WIDTH = WRAP_CONTENT;
    private static final int DEFAULT_HEIGHT = WRAP_CONTENT;
 
    public LayoutParams() {
      super(DEFAULT_WIDTH, DEFAULT_HEIGHT);
      innerPercent = -1.0f;
    }
 
    public LayoutParams(float innerPercent) {
      super(DEFAULT_WIDTH, DEFAULT_HEIGHT);
      this.innerPercent = innerPercent;
    }
 
    public LayoutParams(ViewGroup.LayoutParams p) {
      super(p);
    }
 
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public LayoutParams(LinearLayout.LayoutParams source) {
      super(source);
    }
 
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public LayoutParams(LayoutParams source) {
      super(source);
      this.innerPercent = source.innerPercent;
    }
 
    public LayoutParams(Context c, AttributeSet attrs) {
      super(c, attrs);
      init(c, attrs);
    }
 
    private void init(Context context, AttributeSet attrs) {
      TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomLinearLayout_Layout);
      innerPercent = a.getFloat(R.styleable.CustomLinearLayout_Layout_inner_percent, -1.0f);
      a.recycle();
    }
  }
}
Nach dem Login kopieren

Jetzt können Sie unsere Attribute in XML verwenden.

<?xml version="1.0" encoding="utf-8"?>
<com.egos.samples.custom_layout.CustomLinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="200dp"
  android:layout_height="200dp"
  android:id="@+id/test_layout"
  android:background="#ffff0000"
  android:gravity="center"
  android:orientation="vertical">
  <ImageView
    android:text="Egos"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:onClick="add"
    android:background="#ff00ff00"
    app:inner_percent="0.8"/>
</com.egos.samples.custom_layout.CustomLinearLayout>
Nach dem Login kopieren

Es ist einfach weich und hat keine Wirkung.

Wie steuern Sie also die Größe der untergeordneten Ansicht? Natürlich wird es in onMeasure gesteuert. addView führt den folgenden Code aus.

requestLayout();
invalidate(true);
Nach dem Login kopieren

In diesem Fall werden onMeasure() und onLayout() erneut durchlaufen. Nach der Implementierung der onMeasure()-Methode werde ich die Größe der untergeordneten Ansicht direkt verarbeiten. Da ich LinearLayout erbe, wird MeasureChildBeforeLayout() tatsächlich verarbeitet. Der letzte Schritt besteht darin, die Größe der untergeordneten Ansicht beim Messen von ChildBeforeLayout zu berücksichtigen.

@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec,
                    int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
  // 在xml强制写成match_parent,然后在这里强制设置成
  if (child != null && child.getLayoutParams() instanceof LayoutParams &&
      ((LayoutParams) child.getLayoutParams()).innerPercent != -1.0f) {
    parentWidthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (MeasureSpec.getSize(parentWidthMeasureSpec) *
        ((LayoutParams) child.getLayoutParams()).innerPercent), MeasureSpec.getMode(parentWidthMeasureSpec));
    parentHeightMeasureSpec = MeasureSpec.makeMeasureSpec((int) (MeasureSpec.getSize(parentHeightMeasureSpec) *
        ((LayoutParams) child.getLayoutParams()).innerPercent), MeasureSpec.getMode(parentHeightMeasureSpec));
    super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
      parentHeightMeasureSpec, heightUsed);
  } else {
    super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
        parentHeightMeasureSpec, heightUsed);
  }
}
Nach dem Login kopieren

Auf diese Weise können die ersten Anforderungen erreicht werden.

Zusammenfassung der Verwendung einer benutzerdefinierten ViewGroup in Android

Tatsächlich müssen noch einige Details verarbeitet werden, der folgende Code lautet.

/**
 * 当checkLayoutParams返回false的时候就会执行到这里的generateLayoutParams
 */
 @Override
protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
  return super.generateLayoutParams(lp);
}
 
/**
 * 当addView的时候没有设置LayoutParams的话就会默认执行这里的generateDefaultLayoutParams
 */
@Override
protected LayoutParams generateDefaultLayoutParams() {
  return new LayoutParams();
}
 
/**
 * 写在xml中属性的时候就会执行这里的generateLayoutParams
 */
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
  return new LayoutParams(getContext(), attrs);
}
Nach dem Login kopieren

Um es zusammenzufassen

Worauf Sie beim Anpassen von View und ViewGroup mehr achten müssen, sind onMeasure, onLayout und onDraw.

Trennen Sie die Eigenschaften der ViewGroup selbst und die Eigenschaften der Child View.

Sie können auf den Code im Support-Paket verweisen, und das Debuggen ist ebenfalls sehr praktisch.

Bei der Android-Entwicklung gibt es tatsächlich viele Stellen, an denen Sie Ansichten anpassen müssen, aber die meisten davon verfügen über entsprechende Open-Source-Bibliotheken. Aber wir müssen immer noch wissen, wie man eine ViewGroup anpasst.

Weitere Artikel zur Zusammenfassung der Verwendung benutzerdefinierter ViewGroup in Android finden Sie auf der chinesischen PHP-Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage