Androidでビューの位置を動的に設定するにはどうすればよいですか?


102

コードを使用してビューの位置を変更するにはどうすればよいですか?X、Y位置を変更するように。出来ますか?

回答:


117

Honeycomb(APIレベル11)以下の場合は、を使用する必要がありますsetLayoutParams(...)

あなたは、ハニカムにご支援を制限し、使用することができますアップすることができた場合はsetX(...)setY(...)setLeft(...)setTop(...)、など


40
setTop()developer.android.com/reference/android/view/…のドキュメントから:sets the top position of this view relative to its parent. This method is meant to be called by the layout system and should not generally be called otherwise, because the property may be changed at any time by the layout.-たぶん、それはそれほど良い考えではありません;)
katzenhut

47

はい、Androidでビューの位置を動的に設定できます。同様に、あなたが持っているImageView中でLinearLayout、あなたのxmlのはを通してあなたがその位置を設定することができfile.So LayoutParams.Butを取ることを確認してくださいLayoutParamsあなたのxml file.Thereで撮影したレイアウトに応じて異なってLayoutParams撮影したレイアウトに従って。

設定するコードは次のとおりです。

    LayoutParams layoutParams=new LayoutParams(int width, int height);
    layoutParams.setMargins(int left, int top, int right, int bottom);
    imageView.setLayoutParams(layoutParams);

位置を決めるのに役立つと思います。


15
また、android.widget.LinearLayout.LayoutParamsをインポートする必要があることにも注意してください。デフォルトがViewGroupのLayoutParamsであるため
David T.

これはAndroid 8以降では動作しないようです。同様の問題に直面しましたか?
MyFlashLab 2018

AndriodデザイナーがプログラマーがX、Yを使用して物事を配置するのを防ぐためにそのようなトラブルに行く理由。最終的には、すべてがそのように描かれる必要があります。これは、Androidがコーディングできない人々によって設計されていることを示唆しています。
ポールマッカーシー、

33

すでに有効な回答はいくつかありますが、対応するAPIレベルの制限を除いて、どの場合にどのメソッドを使用するかを適切に提案するものはありません。

  • レイアウトサイクルを待つことができ、親ビューグループがサポートMarginLayoutParams(またはサブクラス)をサポートする場合は、それに応じてmarginLeft/をmarginTop設定します。

  • すぐに永続的に位置を変更する必要がある場合(たとえば、PopupMenuアンカーの場合)、さらにlayout(l, t, r, b)同じ座標で呼び出します。これにより、レイアウトシステムが後で確認する内容が優先されます。

  • すぐに(一時的に)変更(アニメーションなど)を行うには、代わりにsetX()/をsetY()使用します。親のサイズがWRAP_CHILDRENに依存しない場合は、setX()/をsetY()排他的に使用することをお勧めします。

  • setLeft()/ setRight()/ setBottom()/ setTop()は使用しないでください。以下を参照してください。

背景mLeft/ mTop/ mBottom/ mRightフィールドは、layout()の対応するLayoutParamsから入力されます。レイアウトは、Androidビューレイアウトシステムによって暗黙的および非同期的に呼び出されます。したがって、を設定MarginLayoutParamsすることは、位置を永続的に設定するための最も安全でクリーンな方法のようです。ただし、非同期レイアウトの遅延は、たとえばビューを使用してカーソルをレンダリングする場合など、場合によっては問題になる可能性があり、再配置され、同時にPopupMenuアンカーとして機能することが想定されています。この場合、電話layout()はうまくいきました。

setLeft()およびの問題setTop()は次のとおりです。

  • 一人でそれらを呼び出すことは十分ではありません-あなたも呼び出す必要がありますsetRight()し、setBottom()ストレッチやビューを縮小避けるために。

  • これらのメソッドの実装は比較的複雑に見えます(=各メソッドによって引き起こされるビューサイズの変化を考慮するためにいくつかの作業を行っています)

  • それらは入力フィールドで奇妙な問題を引き起こすようです:EditTextソフト数字キーボードは時々数字を許可しません

setX()そしてsetY()作業レイアウトシステムの外側、及び対応する値は、それに応じてビューをシフトする、レイアウトシステムによって決定される左/上/下/右の値にオフセットを追加として扱われます。それらはアニメーション用に追加されたようです(レイアウトサイクルを経由しない即時の効果が必要な場合)。


こんにちはステファン。Androidレイアウトシステムの仕組みを理解できる本や記事をいくつか教えてください。一連のlayout()onMeasure()onDraw()呼び出しを理解していますが、詳細を知りたいです。事前に感謝
セルゲイブラジニック

残念ながらできません-最良かつ最も
信頼

私はsetYを使用してビューを変更しますが、すぐにではなく、次のレイアウトサイクルで変更しますか
信号

これをどのように判断しましたか?
Stefan Haustein、2013

marginLeft設定するを使用setLayoutParamsしてnew FrameLayout.LayoutParams(width, height)で設定できることを指摘する価値がありますmarginLeft
lucidbrot

18

NineOldAndroidsと呼ばれるライブラリがあり、Honeycombアニメーションライブラリをバージョン1まで使用できます。

これは、わずかに異なるインターフェースで、左、右、translationX / Yを定義できることを意味します。

以下にその仕組みを示します。

ViewHelper.setTranslationX(view, 50f);

ViewHelperクラスの静的メソッドを使用して、ビューと、ビューに設定する値を渡します。


16

私が使用することをお勧めします setTranslationXsetTranslationY。私はこれを自分で始めたばかりですが、ビューを移動する最も安全で好ましい方法のようです。それはまさにあなたが何をしようとしているのかに大きく依存していると思いますが、これは私にとって2Dアニメーションでうまく機能しています。


13

HoneyComb Sdk(APIレベル11)を使用している場合は、次の方法を使用してみてください。

view.setX(float x);

パラメータxは、このビューの視覚的なx位置です。

view.setY(float y);

パラメータyは、このビューの視覚的なy位置です。

お役に立てれば幸いです。:)


4
私は2.2 Froyoに取り組んでいますが、これらの方法は利用できません。
Arun Badole、2011

7

すべてのAPIレベルをサポートするには、次のように使用できます。

ViewPropertyAnimator.animate(view).translationYBy(-yourY).translationXBy(-yourX).setDuration(0);

彼は位置を変更したいので、上記の解決策はより優れており、アニメーションを必要としません
FireZenk

また、翻訳によってビューが(部分的に)画面外に移動する可能性があります
mewa

4

このビューの左側の位置を、その親を基準にして設定します。

view.setLeft(int leftPosition);

親を基準にしてこのビューの正しい位置を設定します。

view.setRight(int rightPosition);

親を基準にしてこのビューの上部の位置を設定します。

view.setTop(int topPosition);

親を基準にしてこのビューの下部の位置を設定します。

view.setBottom(int bottomPositon);

上記のメソッドは、親に関連するビューの位置を設定するために使用されます。


これらの方法は使用できません。コードを送っていただけますか?
アルンバドール

4
「このメソッドはレイアウトシステムによって呼び出されることを意図しており、プロパティはいつでもレイアウトによって変更される可能性があるため、通常は他の方法で呼び出すことはできません。」
GDanger 2014年

4

LayoutParamsを使用します。LinearLayoutを使用している場合は、android.widget.LinearLayout.LayoutParamsをインポートする必要があります。それ以外の場合は、使用しているレイアウトの適切なバージョンのLayoutParamsをインポートする必要があります。そうしないと、ClassCastExceptionが発生します

LayoutParams layoutParams = new LayoutParams(int width, int height);
layoutParams.setMargins(int left, int top, int right, int bottom);
imageView.setLayoutParams(layoutParams);

注意:imageView.setLeft(int dim)も使用できますが、これはコンポーネントの位置を設定するのではなく、コンポーネントの左の境界の位置のみを設定します。残りは同じ位置のままです。 。


では、元のビューに影響を与えずにビューを特定の位置に移動するにはどうすればよいでしょうか。
ジェームズ

ビューを移動したい場合、移動しているという事実によってビューを変更するため、問題が理解できたかどうかはわかりません。とにかく、ビューから独立してビューを移動したい場合は、FrameLayoutビューでメインレイアウトを吹き飛ばしてから、その中に独立ビューを配置できます(もちろん、メインビューの下に移動したい場合は、メインフレームフレームの前にFrameLayoutを配置する必要があります)
Alessandro Muzzi

3

を使用しRelativeLayoutてビューを配置し、ビューRelativeLayout.LayoutParamsからオブジェクトを取得して、必要に応じてマージンを設定します。次にrequestLayout()、あなたの見解を求めます。これが私が知っている唯一の方法です。


1

@Stefan Hausteinが私の経験に非常に近いことがわかりましたが、100%確実ではありません。私の提案は:

  • setLeft()/ setRight()/ setBottom()/ setTop()時々動作しません。
  • あなたがしたい場合は (例えば、アニメーションを行うため、hierachyに影響を与えていない)の位置を一時的に設定したときにビューが追加され、示されただけで、使用setX()/setY()代わりに。(あなたは違いもっと検索したいかもしれませんsetLeft()setX()
  • XとYは絶対的なものであり、現在は非推奨となっているAbsoluteLayoutによってサポートされていたことに注意してください。したがって、X、Yはサポートされなくなったと思われます。はい、そうですが、一部だけです。これは、ビューが追加された場合、setX()、setY()が完全に機能することを意味します。それ以外の場合、ビューグループレイアウト(FrameLayout、LinearLayout、RelativeLayoutなど)にビュー追加しようとするとき代わりにmarginLeft、marginTop(この場合setX()、setY()でLayoutParamsを設定する必要あります)を設定する必要あります。
  • marginLeftとmarginTopによるビューの位置の設定は、非同期のプロセスです。そのため、階層を更新するのに少し時間がかかりますマージンを設定した直後にビュー使用する場合、誤った値を取得する可能性があります

0

配置について留意する必要があることの1つは、各ビューには親ビューを基準にしたインデックスがあることです。したがって、3つのサブビューを持つ線形レイアウトの場合、サブビューにはそれぞれインデックスがあります。上記の場合、0、1、2です。

これにより、次のようにして親ビューの最後の位置(または最後)にビューを追加できます。

int childCount = parent.getChildCount();
parentView.addView(newView, childCount);

または、次のようなものを使用してビューを置き換えることもできます。

int childIndex = parentView.indexOfChild(childView);
childView.setVisibility(View.GONE);

parentView.addView(newView, childIndex);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.