How to place views in a specific location (x, y co

2019-01-19 08:18发布

I have a problem with placing my views (my class extends View) in a specific location. I have designed a game that treats the screen as a net of grids. I get from the user x and y coordinates of a specific view (I have different types of views).

My first mission is to set the correct view in its place. How can I do it? I am using RelativeLayout for the screen.

P.S. I don't want to use AbsoluteLayout params because it was truncated.

2条回答
贼婆χ
2楼-- · 2019-01-19 09:16

Suppose u want to place a button on a screen and u have 100x60 cells in ur grid. That is u have divided the screen into 100x60 cells, by considering number of pixels along horizontal and vertical. In landscape mode, the number of width pixels will be more so hence consider dividing it by 100, and the number of height pixels will be less so divide it by 60. So considering that ur using a TAB having resolution 800x480 pixels, In landscape mode - u have 8 pixels(800/100) per cell along horizontal and 8 pixels(480/60) per cell along vertical.The division factor will be vice-versa in portrait mode.

Now u want to place a button of width say 35 cells and height is wrap_content according to the text on it and place it on co-ordinates 20,20(x,y) cell number. I have provided a method to achieve this..And note: What ever view u will place in this fashion or using this idea, it will be in same place and have same dimensions and look and feel on multiple display resolution.[here pixels_grid_X = pixels per cell along horizontal(800/100)] [Similiarly pixels_grid_Y = pixels per cell along vertical(480/60)]

Method for placing a button

public void placeButton(int btnId, int xCordinate, int yCordinate, int btnWidth,
        float fontSize, String btnTextColor, String btnBackgroundColor, String message){



    try{


        int currentApi = Build.VERSION.SDK_INT;
        /** Creating a new Button and setting its properties */
       /**pass context as a parameter for the constructor of the class if ur creating a new class just for placing views on screen,else it can be getBaseContext().*/
        Button btn = new Button(context);
        /**Use to access this view using Id to add any kind of listeners on this view.*/
        btn.setId(btnId);

        btn.setText(message);
        /**Let the text size be in pixels*/
        btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, pixels_grid_X*fontSize);

        if(btnTextColor != null)

        {
            btn.setTextColor(Color.parseColor(btnTextColor));

        }

        int widthInPixel = (int) (btnWidth*pixels_grid_X);
        btn.setWidth(widthInPixel);


        if(btnBackgroundColor != null)
        {

            if(currentApi >= 16){
                btn.setBackground(new ColorDrawable(Color.parseColor(btnBackgroundColor )));
            }
            else
            {
                btn.setBackgroundDrawable(new ColorDrawable(Color.parseColor(btnBackgroundColor )));
            }
            /**Registering for a onTouch listener to provide clicked effect just like a button.
             * To provide a click effect for the custom button*/
            btn.setOnTouchListener(this);
        }
        else
        {   /**If btnBackgroundColor was equal to null, set default properties to that button.*/ 
            btn.setBackgroundResource(android.R.drawable.btn_default);
        }

        /** Providing layout params for the image view.*/
        RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
        params1.leftMargin = (int) (xCordinate*pixels_grid_X);
        params1.topMargin = (int) (yCordinate*pixels_grid_Y);
        btn.setLayoutParams(params1);

        /**
         * The parent layout in which the button is to be displayed.
         * Finally adding the button to the parent layout.
         * layout is the reference to ur relative layout.   
         */

        layout.addView(btn,params1);


    }catch(Exception ex){
        ex.printStackTrace();

    }

}
查看更多
孤傲高冷的网名
3楼-- · 2019-01-19 09:17

This is not the best way to achieve it, but it's a solution...

Create a class that extends your parent ViewGroup, say RelativeLayout or some other ViewGroups. Find your own view in overriding onFinishInflate().

Override the onLayout() method and manually layout your own view after calling super.onLayout().

Finally, every time you want to refresh the location of your own view, just call requestLayout().

Here is a sample below:

private AwesomeView mMyView;
private int mYourDesiredX;
private int mYourDesiredY;

@Override
public void onFinishInflate() {
    super.onFinishInflate();
    if (mMyView == null) {
        mMyView = (AwesomeView)findViewById();
    }
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    mMyView.layout(mYourDesiredX,
            mYourDesiredY,
            mYourDesiredX + mMyView.getWidth(),
            mYourDesiredY + mMyView.getHeight());
}

But this is not an efficient solution.

If you are making games, try SurfaceView or even GLSurfaceView and draw the objects by your own with Canvas.

查看更多
登录 后发表回答