親レイアウトのサイズに基づいてビューのサイズを変更するにはどうすればよいですか。たとえばRelativeLayout
、画面全体に表示されるがあり、子ビュー、たとえばImageView
を使用して、高さ全体、幅の半分を占めるようにしますか?
私は上のすべてを上書きしようとしたonMeasure
、onLayout
、onSizeChanged
...、などと私は仕事にそれを得ることができませんでした
親レイアウトのサイズに基づいてビューのサイズを変更するにはどうすればよいですか。たとえばRelativeLayout
、画面全体に表示されるがあり、子ビュー、たとえばImageView
を使用して、高さ全体、幅の半分を占めるようにしますか?
私は上のすべてを上書きしようとしたonMeasure
、onLayout
、onSizeChanged
...、などと私は仕事にそれを得ることができませんでした
回答:
まだこのスレッドを読んでいる人がいるかどうかはわかりませんが、Jeffの解決策では途中までしか表示されません(文字通り)。彼のonMeasureが行うことは、画像の半分を親の半分に表示することです。問題は、の前にsuper.onMeasureを呼び出すsetMeasuredDimension
と、ビューのすべての子が元のサイズに基づいて測定され、setMeasuredDimension
サイズが変更されたときにビューが半分にカットされることです。
代わりに、setMeasuredDimension
(onMeasureオーバーライドの必要に応じて)を呼び出しLayoutParams
、ビューに新しいを提供してから、を呼び出す必要がありますsuper.onMeasure
。LayoutParams
は、ビューのタイプではなく、ビューの親タイプから派生していることに注意してください。
@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);
}
親に問題が発生するのは、親LayoutParams
がである場合のみですAbsoluteLayout
(非推奨ですが、場合によっては有用です)。
MeasureSpec.getSize(widthMeasureSpec)
本当に正しいparent'sは幅与えますか?私にとっては、実際の幅に非常に近いが正確ではないランダムな幅を返すだけです。
wrap_content
ません。Vicの回答はこのシナリオでは機能しませんが、@ M.Schenkのコメントは機能します。また、追加のレイアウトパスも節約できます。また、可視性のために回答として投稿する必要があります。
super.onMeasure()
以前の呼び出しの効果を単に無効にして無効にする呼び出しではありthis.setMeasuredDimension()
ませんか?
super.onMeasure()
が以前の計算を上書きしないのか、私も興味があります。
これを解決するには、カスタムビューを作成し、onMeasure()メソッドをオーバーライドします。xmlのlayout_widthに常に「fill_parent」を使用する場合、onMeasusre()メソッドに渡されるwidthMeasureSpecパラメーターには、親の幅が含まれている必要があります。
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);
}
}
XMLは次のようになります。
<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>
測定された寸法を自分で設定することをいじらないことが最善であることがわかりました。実際には、親ビューと子ビューの間で行われる少しの交渉があり、そのすべてのコードを書き直したくない。
しかし、できることは、measureSpecsを変更してから、それらを使ってsuperを呼び出すことです。ビューは、親から変更されたメッセージを受け取っていることを決して認識せず、すべてを処理します。
@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);
}
XMLでレイアウトとビューを定義するときに、ビューのレイアウトの幅と高さを指定して、コンテンツをラップするか、親を塗りつぶすことができます。領域の半分を占めるのは少し難しいですが、必要なものがあれば、次の半分のようにすることができます。
<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>
2つのものに同じ重みを与えると、画面の同じ割合を占めるように伸縮します。レイアウトの詳細については、開発者向けドキュメントをご覧ください。
MayrasのXMLアプローチはきっとうまくいくと思います。ただし、weightSumを設定するだけで、1つのビューでより正確にすることができます。私はこれをハックとは呼びませんが、私の意見では最も簡単なアプローチです:
<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>
このように、任意のウェイトを使用できます。たとえば、0.6(およびセンタリング)は、ボタンに使用するウェイトです。
これを試して
int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();
次に、LinearLayout.LayoutParamsを使用して、chileViewのパラメーターを設定できます。
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
これで、PercentRelativeLayoutを使用できます。ブーム!問題が解決しました。
Roman、Javaコード(ViewGroupの子孫)でレイアウトを行いたい場合、それは可能です。コツは、onMeasureメソッドとonLayoutメソッドの両方を実装する必要があることです。onMeasureが最初に呼び出され、サブビューを「測定」して(効果的に目的の値にサイズ変更する)必要があります。onLayout呼び出しでもう一度サイズを変更する必要があります。このシーケンスを実行できなかった場合、またはonMeasureコードの最後でsetMeasuredDimension()を呼び出せなかった場合、結果は得られません。なぜこれがそんなに複雑で壊れやすい方法で設計されているのかは私を超えています。
それは次のようなものです:
<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>