Android 设置视图的绝对位置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3294590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:32:50  来源:igfitidea点击:

Set the absolute position of a view

androidandroid-layoutlayoutviewposition

提问by Sephy

Is it possible to set the absolute position of a view in Android? (I know that there is an AbsoluteLayout, but it's deprecated...)

是否可以在 Android 中设置视图的绝对位置?(我知道有一个AbsoluteLayout,但它已被弃用......)

For example, if I have a 240x320px screen, how could I add an ImageViewwhich is 20x20px such that its center is at the position (100,100)?

例如,如果我有一个 240x320 像素的屏幕,我如何添加一个 20x20 像素的屏幕,ImageView使其中心位于 (100,100) 位置?

回答by Andy Zhang

You can use RelativeLayout. Let's say you wanted a 30x40 ImageView at position (50,60) inside your layout. Somewhere in your activity:

您可以使用相对布局。假设您想要在布局内的位置 (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);


More examples:

更多例子:

Places two 30x40 ImageViews (one yellow, one red) at (50,60) and (80,90), respectively:

分别在 (50,60) 和 (80,90) 处放置两个 30x40 ImageViews(一个黄色,一个红色):

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);

Places one 30x40 yellow ImageView at (50,60) and another 30x40 red ImageView <80,90> relative tothe yellow ImageView:

将一个 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);

回答by bonnyz

In general, you can add a View in a specific position using a FrameLayout as container by specifying the leftMargin and topMargin attributes.

通常,您可以通过指定 leftMargin 和 topMargin 属性,使用 FrameLayout 作为容器在特定位置添加 View

The following example will place a 20x20px ImageView at position (100,200) using a FrameLayout as fullscreen container:

以下示例将使用 FrameLayout 作为全屏容器在位置 (100,200) 放置一个 20x20 像素的 ImageView:

XML

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>

Activity / Fragment / Custom view

活动/片段/自定义视图

//...
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);
//...

This will do the trick because margins can be used as absolute (X,Y) coordinates without a RelativeLayout:

这可以解决问题,因为边距可以用作没有相对布局的绝对 (X,Y) 坐标:

enter image description here

在此处输入图片说明

回答by Excrubulent

Just to add to Andy Zhang's answer above, if you want to, you can give param to rl.addView, then make changes to it later, so:

只是为了补充上面安迪张的回答,如果你愿意,你可以给 rl.addView 参数,然后稍后对其进行更改,因此:

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

Could equally well be written as:

同样可以写成:

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

So if you retain the params variable, you can change the layout of iv at any time after adding it to rl.

所以如果你保留params变量,你可以在将它添加到rl后随时更改iv的布局。

回答by Hari Krishna Ganji

A more cleaner and dynamic way without hardcoding any pixel values in the code.

一种更简洁和动态的方式,无需在代码中硬编码任何像素值。

I wanted to position a dialog (which I inflate on the fly) exactly below a clicked button.

我想在单击的按钮正下方放置一个对话框(我会即时膨胀)。

and solved it this way :

并以这种方式解决它:

    // 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;
    }

However you have to make sure the parent layout of myViewis an instance of RelativeLayout.

但是,您必须确保 的父布局myViewRelativeLayout.

more complete code :

更完整的代码:

    // 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;
    }

This way you can still expect the target view to adjust to any layout parameters set using layout XML files, instead of hardcoding those pixels/dps in your Java code.

通过这种方式,您仍然可以期望目标视图调整为使用布局 XML 文件设置的任何布局参数,而不是在 Java 代码中对这些像素/dps 进行硬编码。

回答by Hiren Patel

Check screenshot

检查截图

Place any view on your desire X& Ypoint

将任何视图放在您想要的XY点上

layout file

布局文件

<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 Class

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);
    }
}

Done

完毕

回答by praveenb

Just in case it may help somebody, you may also try this animator ViewPropertyAnimatoras below

以防万一它可以帮助某人,您也可以尝试这个动画师ViewPropertyAnimator如下

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

myView.animate().translateX(pixelInScreen) 

Note: This pixel is not relative to the view. This pixel is the pixel position in the screen.

注意:此像素与视图无关。这个像素是屏幕中的像素位置。

credits to bpr10 answer

归功于bpr10 答案

回答by duggu

Try below code to set view on specific location :-

尝试使用以下代码在特定位置设置视图:-

            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);

回答by Technacron

My code for Xamarin, I am using FrameLayoutfor this purpose and following is my code:

我的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;
                    }

            }

        }

It was useful for me because I needed the property of view to overlap each other on basis of their appearance, e.g the views get stacked one above other.

这对我很有用,因为我需要视图的属性根据它们的外观相互重叠,例如,视图堆叠在一起