it-swarm.com.de

Wie kann man eine Android Ansicht basierend auf den Abmessungen der Eltern skalieren?

Wie kann ich eine Ansicht basierend auf der Größe des übergeordneten Layouts skalieren? Zum Beispiel habe ich ein RelativeLayout, das den gesamten Bildschirm ausfüllt, und ich möchte, dass eine untergeordnete Ansicht, z. B. ein ImageView, die gesamte Höhe und die Hälfte der Breite einnimmt.

Ich habe versucht, alle auf onMeasure, onLayout, onSizeChanged usw. zu überschreiben, und ich konnte es nicht zum Laufen bringen ....

99
Mitch

Ich weiß nicht, ob noch jemand diesen Thread liest oder nicht, aber Jeffs Lösung wird Sie nur auf halbem Weg dorthin bringen (ein bisschen wörtlich). Was sein onMeasure tun wird, ist das halbe Bild im halben übergeordneten Element anzuzeigen. Das Problem besteht darin, dass beim Aufrufen von super.onMeasure vor dem setMeasuredDimension alle untergeordneten Elemente in der Ansicht anhand der Originalgröße gemessen werden. Anschließend wird die Ansicht nur halbiert, wenn die Größe des setMeasuredDimension geändert wird.

Stattdessen müssen Sie setMeasuredDimension aufrufen (wie für eine OnMeasure-Überschreibung erforderlich) nd Ihrer Ansicht nach ein neues LayoutParams bereitstellen, dann aufrufen super.onMeasure. Denken Sie daran, dass Ihr LayoutParams vom übergeordneten Typ Ihrer Ansicht und nicht vom Typ Ihrer Ansicht abgeleitet wird.

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
   int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
   int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
   this.setMeasuredDimension(parentWidth/2, parentHeight);
   this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
   super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

Ich glaube, das einzige Mal, dass Sie Probleme mit dem übergeordneten LayoutParams haben, ist, wenn das übergeordnete AbsoluteLayout ist (was veraltet, aber manchmal immer noch nützlich ist).

122
Vic

Sie können dieses Problem beheben, indem Sie eine benutzerdefinierte Ansicht erstellen und die Methode onMeasure () überschreiben. Wenn Sie immer "fill_parent" für die layout_width in Ihrer XML-Datei verwenden, sollte der widthMeasureSpec-Parameter, der an die onMeasusre () -Methode übergeben wird, die Breite des übergeordneten Elements enthalten.

public class MyCustomView extends TextView {

    public MyCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(parentWidth / 2, parentHeight);
    }
}   

Ihr XML würde ungefähr so ​​aussehen:

<LinearLayout 
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">
    <view
        class="com.company.MyCustomView"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent" />
</LinearLayout>
39
Jeff

Ich habe festgestellt, dass es am besten ist, die gemessenen Abmessungen nicht selbst einzustellen. Tatsächlich wird zwischen der übergeordneten und der untergeordneten Ansicht ein bisschen verhandelt, und Sie möchten nicht alles neu schreiben Code .

Sie können jedoch die measureSpecs ändern und dann super mit ihnen aufrufen. Ihre Ansicht wird nie erfahren, dass sie eine geänderte Nachricht von ihrem übergeordneten Element erhält, und sich um alles für Sie kümmern:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
    int myWidth = (int) (parentHeight * 0.5);
    super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
25
Phil Kulak

Wenn Sie ein Layout und eine Ansicht in XML definieren, können Sie die Layoutbreite und -höhe einer Ansicht so festlegen, dass der Inhalt umbrochen oder die übergeordnete Ansicht ausgefüllt wird. Die Hälfte der Fläche einzunehmen ist etwas schwieriger, aber wenn Sie etwas hatten, das Sie auf der anderen Hälfte wollten, könnten Sie etwas wie das Folgende tun.

   <LinearLayout Android:layout_width="fill_parent"
                Android:layout_height="fill_parent">
        <ImageView Android:layout_height="fill_parent"
                 Android:layout_width="0dp"
                 Android:layout_weight="1"/>
        <ImageView Android:layout_height="fill_parent"
                 Android:layout_width="0dp"
                 Android:layout_weight="1"/>
   </LinearLayout>

Wenn Sie zwei Dingen das gleiche Gewicht geben, bedeutet dies, dass sie sich dehnen, um den gleichen Anteil des Bildschirms einzunehmen. Weitere Informationen zu Layouts finden Sie unter die Entwicklerdokumente

15
Cheryl Simon

Ich glaube, dass Mayras XML-Ansatz in ordentlich kommen kann. Es ist jedoch möglich, die Genauigkeit mit nur einer Ansicht zu verbessern, indem Sie die Gewichtssumme einstellen. Ich würde das nicht mehr als Hack bezeichnen, aber meiner Meinung nach ist es der einfachste Ansatz:

<LinearLayout Android:layout_width="fill_parent"
              Android:layout_height="fill_parent"
              Android:weightSum="1">
    <ImageView Android:layout_height="fill_parent"
               Android:layout_width="0dp"
               Android:layout_weight="0.5"/>
</LinearLayout>

Auf diese Weise können Sie ein beliebiges Gewicht verwenden, z. B. 0,6 (und Zentrierung) ist das Gewicht, das ich für Schaltflächen gerne verwende.

9
pinkwerther

Versuche dies

int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();

dann können Sie LinearLayout.LayoutParams zum Einstellen der Parameter von chileView verwenden

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
3
Abhishek Gupta

Sie können jetzt PercentRelativeLayout verwenden. Boom! Problem gelöst.

2
androidguy

Wenn die andere Seite leer ist. Ich denke, der einfachste Weg wäre, eine leere Ansicht (z. B. ein lineares Layout) hinzuzufügen und dann die Breite beider Ansichten auf fill_parent und ihre Gewichtung auf 1 zu setzen.

Dies funktioniert in einem LinearLayout ...

1
jpm

Roman, wenn Sie Ihr Layout in Java Code (ViewGroup-Nachkomme) erstellen möchten, ist dies möglich. Der Trick besteht darin, dass Sie sowohl die onMeasure-Methode als auch die onLayout-Methode implementieren müssen. Die onMeasure-Methode wird zuerst und dann aufgerufen Sie müssen die Unteransicht dort "messen" (effektiv auf den gewünschten Wert skalieren). Sie müssen sie im OnLayout-Aufruf erneut skalieren. Wenn Sie diese Sequenz nicht ausführen oder setMeasuredDimension () am Ende Ihres OnMeasure nicht aufrufen Warum das so kompliziert und fragil gestaltet ist, ist mir ein Rätsel.

1
Pavel Lahoda

Es ist ungefähr so:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.company.myapp.ActivityOrFragment"
    Android:id="@+id/activity_or_fragment">

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:id="@+id/linearLayoutFirst"
    Android:weightSum="100">   <!-- Overall weights sum of children elements -->

    <Spinner
        Android:layout_width="0dp"   <!-- It's 0dp because is determined by Android:layout_weight -->
        Android:layout_weight="50"
        Android:layout_height="wrap_content"
        Android:id="@+id/spinner" />

</LinearLayout>


<LinearLayout
    Android:layout_height="wrap_content"
    Android:layout_width="match_parent"
    Android:layout_below="@+id/linearLayoutFirst"
    Android:layout_alignParentLeft="true"
    Android:layout_alignParentStart="true"
    Android:id="@+id/linearLayoutSecond">

    <EditText
        Android:layout_height="wrap_content"
        Android:layout_width="0dp"
        Android:layout_weight="75"
        Android:inputType="numberDecimal"
        Android:id="@+id/input" />

    <TextView
        Android:layout_height="wrap_content"
        Android:layout_width="0dp"
        Android:layout_weight="25"
        Android:id="@+id/result"/>

</LinearLayout>
</RelativeLayout>
0
Mario