ビューの絶対位置を設定する


180

Androidでビューの絶対位置を設定することは可能ですか?(があることは知っていますが、AbsoluteLayout非推奨です...)

たとえば、240x320pxの画面がある場合ImageView、中心が(100,100)の位置になるように20x20pxのを追加するにはどうすればよいですか?


3
また、view.setTranslationX()またはview.offsetLeftAndRight()
Drew LeSueur 2013年

ここで興味を持ったと思われるライブラリをリリースしました。github.com/ManuelPeinado/ImageLayout
Manuel

1
時間の99.9%の絶対配置はAndroidでは悪い考えであるため、これは非常に困難です。1つの物理デバイスでのみ実行されるアプリを作成している場合、これは機能する可能性がありますが、一般的に安全な想定ではありません。たとえば、これをGoogle Playにアップロードしないでください。少数のハードウェアデバイスしかないため、iOSでは正常に動作し、デバイスごとにカスタムストーリーボードを作成できます。
2015年

2
@edthethird、私のクロスプラットフォームアプリでは、画面サイズを取得し、それに基づいてすべてを行います。「廃止された」AbsoluteLayoutに切り替えたところ、問題なく動作しました。
William Jockusch 2015年

十分に公正ですが、これは相対レイアウトまたはLinearLayoutが自動的に行うことです。
2015年

回答:


271

RelativeLayoutを使用できます。レイアウト内の位置(50,60)に30x40のImageViewが必要だとします。あなたの活動のどこかに:

// Some existing RelativeLayout from your layout xml
RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);

ImageView iv = new ImageView(this);

RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

その他の例:

2つの30x40 ImageViews(1つは黄色、1つは赤)をそれぞれ(50,60)と(80,90)に配置します。

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

iv = new ImageView(this);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;
rl.addView(iv, params);

1つの30x40黄色のImageViewを(50,60)に配置し、別の30x40赤色のImageView <80,90> 黄色のImageView に対して配置します。

RelativeLayout rl = (RelativeLayout) findViewById(R.id.my_relative_layout);
ImageView iv;
RelativeLayout.LayoutParams params;

int yellow_iv_id = 123; // Some arbitrary ID value.

iv = new ImageView(this);
iv.setId(yellow_iv_id);
iv.setBackgroundColor(Color.YELLOW);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

iv = new ImageView(this);
iv.setBackgroundColor(Color.RED);
params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 80;
params.topMargin = 90;

// This line defines how params.leftMargin and params.topMargin are interpreted.
// In this case, "<80,90>" means <80,90> to the right of the yellow ImageView.
params.addRule(RelativeLayout.RIGHT_OF, yellow_iv_id);

rl.addView(iv, params);

1
今夜、私はそれを試してみるつもりです、それはかなりいい考えです、なぜ私がそれについて考えなかったのか分かりません。いくつか挙げImageViewておきますが、FrameLayout
Sephy、2010

確かにこれは機能しているようですが、この方法で1つの画像を追加した場合にのみ機能します。私は2番目の1を追加しようとした場合、最初のものはちょうど...消える
Sephy

1
2つの画像はちょうど重なり合っています。上記のソリューションにコードを追加して説明します。
Andy Zhang

2
ええ、確かに、私は昨日も自分で解決策を掘り下げて見つけました。また、FrameLayoutを使って試します。私の実際の問題は、ランダムな(x、y)位置にそれぞれ5つの画像があるため、RelativeLayout.RIGHT_OFなどを使用できないことです。奇妙なことに、3つの画像を適切に配置できますが、2つが機能しません...わかりません...今夜、スクリーンショットとコードをいくつか投稿して更新します。
Sephy、

9
このメソッドを使用することがAbsoluteLayoutを使用するよりも優れているのはなぜですか?AbsoluteLayoutが廃止されたからといって?
ネイサン

66

一般に、leftMarginおよびtopMargin属性を指定することにより、コンテナーとしてFrameLayoutを使用して特定の位置にビューを追加できます

次の例では、フルスクリーンコンテナーとしてFrameLayoutを使用して、位置(100,200)に20x20px ImageViewを配置します。

XML

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:background="#33AAFF"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

アクティビティ/フラグメント/カスタムビュー

//...
FrameLayout root = (FrameLayout)findViewById(R.id.root);
ImageView img = new ImageView(this);
img.setBackgroundColor(Color.RED);
//..load something inside the ImageView, we just set the background color

FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(20, 20);
params.leftMargin = 100;
params.topMargin  = 200;
root.addView(img, params);
//...

マージンはRelativeLayoutなしで絶対(X、Y)座標として使用できるため、これでうまくいきます。

ここに画像の説明を入力してください


2
鮮やかさ!500に値する!+1
リサアン

16

上記のAndy Zhangの回答に追加するために、必要に応じてparamをrl.addViewに指定し、後で変更することができます。

params = new RelativeLayout.LayoutParams(30, 40);
params.leftMargin = 50;
params.topMargin = 60;
rl.addView(iv, params);

同様に次のように書くこともできます:

params = new RelativeLayout.LayoutParams(30, 40);
rl.addView(iv, params);
params.leftMargin = 50;
params.topMargin = 60;

したがって、params変数を保持している場合は、rlに追加した後、いつでもivのレイアウトを変更できます。


このサンプルを追加しました。xmlレイアウトで画像を持っているときに、x、y軸をどのように設定できますか(画像のサイズを変更しようとしていて、画像をある位置に設定する必要がある)
G_S

質問の内容がよくわかりません。XMLレイアウトを使用して配置されたオブジェクトに関連付けられているLayoutParamsオブジェクトにアクセスしようとしていますか?それがどのように行われるのかわかりません。他の場所で答えが見つからない場合は、これを答えるために新しい質問を設定することをお勧めします。
Excrubulent

この質問を見ていてくださいstackoverflow.com/questions/12028404/...を
G_S

5

コード内のピクセル値をハードコーディングすることなく、よりクリーンでダイナミックな方法。

クリックしたボタンの真下にダイアログ(その場で膨らます)を配置したいと思いました。

このように解決しました:

    // get the yoffset of the position where your View has to be placed 
    final int yoffset = < calculate the position of the view >

    // position using top margin
    if(myView.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) myView.getLayoutParams()).topMargin = yOffset;
    }

ただし、の親レイアウトmyViewがのインスタンスであることを確認する必要がありますRelativeLayout

より完全なコード:

    // identify the button
    final Button clickedButton = <... code to find the button here ...>

    // inflate the dialog - the following style preserves xml layout params
    final View floatingDialog = 
        this.getLayoutInflater().inflate(R.layout.floating_dialog,
            this.floatingDialogContainer, false);

    this.floatingDialogContainer.addView(floatingDialog);

    // get the buttons position
    final int[] buttonPos = new int[2];
    clickedButton.getLocationOnScreen(buttonPos);        
    final int yOffset =  buttonPos[1] + clickedButton.getHeight();

    // position using top margin
    if(floatingDialog.getLayoutParams() instanceof MarginLayoutParams) {
        ((MarginLayoutParams) floatingDialog.getLayoutParams()).topMargin = yOffset;
    }

このようにしても、Javaコードでピクセル/ dpsをハードコーディングする代わりに、レイアウトXMLファイルを使用して設定されたレイアウトパラメーターにターゲットビューが調整されることを期待できます。


1

スクリーンショットを確認する

あなたの欲望のXYポイントに任意のビューを配置

レイアウトファイル

<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.example.test.MainActivity" >

    <AbsoluteLayout
        android:id="@+id/absolute"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <RelativeLayout
            android:id="@+id/rlParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <ImageView
                android:id="@+id/img"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/btn_blue_matte" />
        </RelativeLayout>
    </AbsoluteLayout>

</RelativeLayout>

Javaクラス

public class MainActivity extends Activity {

    private RelativeLayout rlParent;
    private int width = 100, height = 150, x = 20, y= 50; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AbsoluteLayout.LayoutParams param = new AbsoluteLayout.LayoutParams(width, height, x, y);
        rlParent = (RelativeLayout)findViewById(R.id.rlParent);
        rlParent.setLayoutParams(param);
    }
}

できた


0

誰かを助けるかもしれない場合に備えて、このアニメーターViewPropertyAnimatorを以下のように試すこともできます

myView.animate().x(50f).y(100f);

myView.animate().translateX(pixelInScreen) 

注:このピクセルはビューに関連していません。このピクセルは、画面内のピクセル位置です。

bpr10回答へのクレジット


-1

特定の場所にビューを設定するには、以下のコードを試してください:-

            TextView textView = new TextView(getActivity());
            textView.setId(R.id.overflowCount);
            textView.setText(count + "");
            textView.setGravity(Gravity.CENTER);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
            textView.setTextColor(getActivity().getResources().getColor(R.color.white));
            textView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // to handle click 
                }
            });
            // set background 
            textView.setBackgroundResource(R.drawable.overflow_menu_badge_bg);

            // set apear

            textView.animate()
                    .scaleXBy(.15f)
                    .scaleYBy(.15f)
                    .setDuration(700)
                    .alpha(1)
                    .setInterpolator(new BounceInterpolator()).start();
            FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT);
            layoutParams.topMargin = 100; // margin in pixels, not dps
            layoutParams.leftMargin = 100; // margin in pixels, not dps
            textView.setLayoutParams(layoutParams);

            // add into my parent view
            mainFrameLaout.addView(textView);

-1

Xamarinの私のコード、この目的のためにFrameLayoutを使用しており、以下が私のコードです。

               List<object> content = new List<object>();

        object aWebView = new {ContentType="web",Width="300", Height = "300",X="10",Y="30",ContentUrl="http://www.google.com" };
        content.Add(aWebView);
        object aWebView2 = new { ContentType = "image", Width = "300", Height = "300", X = "20", Y = "40", ContentUrl = "https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4" };
        content.Add(aWebView2);
        FrameLayout myLayout = (FrameLayout)FindViewById(Resource.Id.frameLayout1);
        foreach (object item in content)
        {

            string contentType = item.GetType().GetProperty("ContentType").GetValue(item, null).ToString();
            FrameLayout.LayoutParams param = new FrameLayout.LayoutParams(Convert.ToInt32(item.GetType().GetProperty("Width").GetValue(item, null).ToString()), Convert.ToInt32(item.GetType().GetProperty("Height").GetValue(item, null).ToString()));
            param.LeftMargin = Convert.ToInt32(item.GetType().GetProperty("X").GetValue(item, null).ToString());
            param.TopMargin = Convert.ToInt32(item.GetType().GetProperty("Y").GetValue(item, null).ToString());

            switch (contentType) {
                case "web":{
                        WebView webview = new WebView(this);

                        //webview.hei;
                        myLayout.AddView(webview, param);
                        webview.SetWebViewClient(new WebViewClient());
                        webview.LoadUrl(item.GetType().GetProperty("ContentUrl").GetValue(item, null).ToString());

                        break;
                    }
                case "image":
                    {
                        ImageView imageview = new ImageView(this);

                        //webview.hei;
                        myLayout.AddView(imageview, param);
                        var imageBitmap =  GetImageBitmapFromUrl("https://www.nasa.gov/sites/default/files/styles/image_card_4x3_ratio/public/thumbnails/image/leisa_christmas_false_color.png?itok=Jxf0IlS4");
                        imageview.SetImageBitmap(imageBitmap);


                        break;
                    }

            }

        }

私は、ビューが取得例えば、その外観に基づいて相互に重なるように、ビューのプロパティを必要なので、それは私のために有用であった一方が他方の上に積み重ねられました

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