代码之家  ›  专栏  ›  技术社区  ›  Boardy

获取视图每个角的位置,然后在该位置添加视图

  •  4
  • Boardy  · 技术社区  · 6 年前

    我在一个android项目中工作,我有一个自定义视图。单击自定义视图时,我希望在视图的每个角上放置一个视图(一个圆)。

    目前,我只是想让它在左上角工作,但它最终在中间。

    下面是添加视图的单击函数。

    View view = LayoutInflater.from(getContext()).inflate(R.layout.view, this, false);
    
            TextView textItem = view.findViewById(R.id.lblItemText);
    
            textItem.setText("View: " + counter);
    
            view.setOnClickListener(new OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
    
                    Anchor anchor1 = new Anchor(getContext());
    
                    anchor1.setLeft(v.getLeft());
                    anchor1.setTop(CustomView.this.getTop());
                    CustomView.this.addView(anchor1);
                }
            });
    

    自定义视图位于相对布局内。自定义视图扩展relativelayout和锚定视图,锚定视图应该进入自定义视图扩展按钮的左上角。

    锚点构造函数包含以下内容:

    public Anchor(Context context)
        {
            super(context);
            this.setBackgroundResource(R.drawable.anchor);
            this.setPadding(0,0,0,0);
            this.setWidth(1);
            this.setHeight(1);
    }
    

    由于某种原因,锚出现在中间而不是下面所示的拐角处

    What the end result is

    下面有点期待。

    Expected view

    更新

    几天后取得了一些进展,我确实让它工作,除了它使用硬编码值使它处于正确的位置,这似乎是不对的。我猜这只适用于我正在测试的特定设备,另一个分辨率不同的设备将定位错误。

    下面是我所拥有的代码,希望能显示出我正在努力实现的目标,以及一个关于我现在拥有的东西的截图。

    private void createAnchorPoints()
        {
    
            //Main View
            ViewGroup mainView = activity.findViewById(android.R.id.content);
    
            int[] viewToBeResizedLoc = new int[2];
            viewToBeResized.getLocationOnScreen(viewToBeResizedLoc);
    
    
            //Add top left anchor
            Anchor topLeftAnchor = new Anchor(context, Anchor.ResizeMode.TOP_LEFT);
            FrameLayout.LayoutParams topLeftParms = new FrameLayout.LayoutParams(150,150);
            topLeftParms.leftMargin = viewToBeResizedLoc[0] - 50;
            topLeftParms.topMargin = viewToBeResizedLoc[1] - viewToBeResized.getHeight() - 30;
            topLeftAnchor.setLayoutParams(topLeftParms);
            mainView.addView(topLeftAnchor);
    
            //Add top right anchor
            Anchor topRightAnchor = new Anchor(context, Anchor.ResizeMode.TOP_RIGHT);
            FrameLayout.LayoutParams topRightParms = new FrameLayout.LayoutParams(150, 150);
            topRightParms.leftMargin = topLeftParms.leftMargin + viewToBeResized.getWidth() - 40;
            topRightParms.topMargin = topLeftParms.topMargin;
            topRightAnchor.setLayoutParams(topRightParms);
            mainView.addView(topRightAnchor);
    
            //Add bottom left anchor
            Anchor bottomLeftAnchor = new Anchor(context, Anchor.ResizeMode.BOTTOM_LEFT);
            FrameLayout.LayoutParams bottomLeftParms = new FrameLayout.LayoutParams(150, 150);
            bottomLeftParms.leftMargin = topLeftParms.leftMargin;
            bottomLeftParms.topMargin = topLeftParms.topMargin + viewToBeResized.getHeight() - 40;
            bottomLeftAnchor.setLayoutParams(bottomLeftParms);
            mainView.addView(bottomLeftAnchor);
    
            //Add bottom right anchor
            Anchor bottomRightAnchor = new Anchor(context, Anchor.ResizeMode.BOTTOM_RIGHT);
            FrameLayout.LayoutParams bottomRightParms = new FrameLayout.LayoutParams(150, 150);
            bottomRightParms.leftMargin = topRightParms.leftMargin;
            bottomRightParms.topMargin = bottomLeftParms.topMargin;
            bottomRightAnchor.setLayoutParams(bottomRightParms);
            mainView.addView(bottomRightAnchor);
    
        }
    

    Current example after update

    1 回复  |  直到 6 年前
        1
  •  3
  •   Cheticamp    6 年前

    因为顶层布局是 RelativeLayout ,您将需要使用可用于 相对布局 去实现你想要的。(见 documentation )

    这是一个您想要用xml实现的模型。这个模型将演示我们如何处理实际的解决方案。我使用的是标准视图,但这不重要。此技术将应用于自定义视图。图片来自android studio的设计器,因此没有使用代码创建图片。

    enter image description here

    活动\主.xml

    <RelativeLayout 
        android:id="@+id/relativeLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <RelativeLayout
            android:id="@+id/customView"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_centerInParent="true"
            android:background="@android:color/holo_green_light" />
    
        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignStart="@id/customView"
            android:layout_alignTop="@id/customView"
            android:src="@drawable/circle"
            android:translationX="-10dp"
            android:translationY="-10dp" />
    
        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignEnd="@id/customView"
            android:layout_alignTop="@id/customView"
            android:src="@drawable/circle"
            android:translationX="10dp"
            android:translationY="-10dp" />
    
        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignBottom="@id/customView"
            android:layout_alignStart="@id/customView"
            android:src="@drawable/circle"
            android:translationX="-10dp"
            android:translationY="10dp" />
    
        <ImageView
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_alignBottom="@id/customView"
            android:layout_alignEnd="@id/customView"
            android:src="@drawable/circle"
            android:translationX="10dp"
            android:translationY="10dp" />
    
    </RelativeLayout>
    

    圆.xml

    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
        <!-- fill color -->
        <solid android:color="@android:color/holo_red_light" />
        <size
            android:width="20dp"
            android:height="20dp" />
    </shape>
    

    实际解决方案

    现在,我们已经演示了模拟方法的工作原理,现在我们必须在代码中重现这种效果。我们必须添加圆视图并将其定位在父视图中 相对布局 使用 相对布局 查看定位和翻译。下面的代码只显示了左上角的圆,但其他圆将以类似的方式定位。

    活动\主.java

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Drawable circle = ContextCompat.getDrawable(this, R.drawable.circle);
            ImageView imageView = new ImageView(this);
            imageView.setImageDrawable(circle);
            int circleSize = dpToPx(CIRCLE_SIZE_DP);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(circleSize, circleSize);
    
            // Position top left circle within the custom view.
            lp.addRule(RelativeLayout.ALIGN_START, R.id.customView);
            lp.addRule(RelativeLayout.ALIGN_TOP, R.id.customView);
    
            // Uncomment these 2 lines to position the top left circle with translation.
            imageView.setTranslationX(-circleSize / 2);
            imageView.setTranslationY(-circleSize / 2);
    
            // Uncomment these 3 lines to position the top left circle with margins.
    //        View customView = findViewById(R.id.customView);
    //        lp.leftMargin = customView.getLeft() - circleSize / 2;
    //        lp.topMargin = customView.getTop() - circleSize / 2;
    
            ((RelativeLayout) findViewById(R.id.relativeLayout)).addView(imageView, lp);
        }
    
        private int dpToPx(int dp) {
            return (int) (dp * getResources().getDisplayMetrics().density);
        }
    
        private static final int CIRCLE_SIZE_DP = 20;
    }
    

    上面的代码使用了一个缩短的布局:

    活动\主.xml

    <RelativeLayout 
        android:id="@+id/relativeLayout"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <RelativeLayout
            android:id="@+id/customView"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_centerInParent="true"
            android:background="@android:color/holo_green_light" />
    
    </RelativeLayout>
    

    也可以使用边距产生相同的定位。使用页边距的代码已被注释掉,但将起作用。(我认为负利润率也可能起作用,但据我所知 officially supported ,所以我尽量避开它们。)