我创建了一些自定义元素,并希望以编程方式将它们放置在右上角(距离上边缘n个像素,距离右边缘m个像素)。因此,我需要获得屏幕宽度和屏幕高度,然后设置位置:

int px = screenWidth - m;
int py = screenHeight - n;

如何在主活动中获取screenWidth和screenHeight?


当前回答

如果Display类不工作,则上面的答案将不起作用,那么您可以通过下面的方法获得宽度和高度。

private static final int WIDTH_INDEX = 0;
private static final int HEIGHT_INDEX = 1;

    public static int[] getScreenSize(Context context) {
        int[] widthHeight = new int[2];
        widthHeight[WIDTH_INDEX] = 0;
        widthHeight[HEIGHT_INDEX] = 0;

        try {
            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();

            Point size = new Point();
            display.getSize(size);
            widthHeight[WIDTH_INDEX] = size.x;
            widthHeight[HEIGHT_INDEX] = size.y;

            if (!isScreenSizeRetrieved(widthHeight))
            {
                DisplayMetrics metrics = new DisplayMetrics();
                display.getMetrics(metrics);
                widthHeight[0] = metrics.widthPixels;
                widthHeight[1] = metrics.heightPixels;
            }

            // Last defense. Use deprecated API that was introduced in lower than API 13
            if (!isScreenSizeRetrieved(widthHeight)) {
                widthHeight[0] = display.getWidth(); // deprecated
                widthHeight[1] = display.getHeight(); // deprecated
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return widthHeight;
    }

    private static boolean isScreenSizeRetrieved(int[] widthHeight) {
        return widthHeight[WIDTH_INDEX] != 0 && widthHeight[HEIGHT_INDEX] != 0;
    }

其他回答

它可能无法回答您的问题,但如果你需要一个视图的维度,但你的代码在尚未布局时(例如在onCreate()中)正在执行,你可以使用View.getViewTreeObserver().addOnGlobalLayoutListener()设置一个ViewTreeObserver.OnGlobalLayout侦听器,并将需要该视图的相关代码放入尺寸。布局布局完成后,将调用侦听器的回调。

最简单的方法:

 int screenHeight = getResources().getDisplayMetrics().heightPixels;
 int screenWidth = getResources().getDisplayMetrics().widthPixels; 

有一种使用DisplayMetrics(API 1)来实现这一点的方法并不过时,它可以避免try/catch混乱:

 // initialize the DisplayMetrics object
 DisplayMetrics deviceDisplayMetrics = new DisplayMetrics();

 // populate the DisplayMetrics object with the display characteristics
 getWindowManager().getDefaultDisplay().getMetrics(deviceDisplayMetrics);

 // get the width and height
 screenWidth = deviceDisplayMetrics.widthPixels;
 screenHeight = deviceDisplayMetrics.heightPixels;

在活动的onCreate中,有时需要知道布局可用空间的精确尺寸。经过一番思考,我想出了这种方法。

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startActivityForResult(new Intent(this, Measure.class), 1);
        // Return without setting the layout, that will be done in onActivityResult.
    }

    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data) {
        // Probably can never happen, but just in case.
        if (resultCode == RESULT_CANCELED) {
            finish();
            return;
        }
        int width = data.getIntExtra("Width", -1);
        // Width is now set to the precise available width, and a layout can now be created.            ...
    }
}

public final class Measure extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
       // Create a LinearLayout with a MeasureFrameLayout in it.
        // Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.
        LinearLayout linearLayout = new LinearLayout(this);
        LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);
        measureFrameLayout.setLayoutParams(matchParent);
        linearLayout.addView(measureFrameLayout);
        this.addContentView(linearLayout, matchParent);
        // measureFrameLayout will now request this second activity to finish, sending back the width.
    }

    class MeasureFrameLayout extends FrameLayout {
        boolean finished = false;
        public MeasureFrameLayout(Context context) {
            super(context);
        }

        @SuppressLint("DrawAllocation")
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if (finished) {
                return;
            }
            finished = true;
            // Send the width back as the result.
            Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));
            Measure.this.setResult(Activity.RESULT_OK, data);
            // Tell this activity to finish, so the result is passed back.
            Measure.this.finish();
        }
    }
}

如果出于某种原因,您不想将另一个活动添加到Android清单中,可以这样做:

public class MainActivity extends Activity {
    static Activity measuringActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        Bundle extras = getIntent().getExtras();
        if (extras == null) {
            extras = new Bundle();
        }
        int width = extras.getInt("Width", -2);
        if (width == -2) {
            // First time in, just start another copy of this activity.
            extras.putInt("Width", -1);
            startActivityForResult(new Intent(this, MainActivity.class).putExtras(extras), 1);
            // Return without setting the layout, that will be done in onActivityResult.
            return;
        }
        if (width == -1) {
            // Second time in, here is where the measurement takes place.
            // Create a LinearLayout with a MeasureFrameLayout in it.
            // Just putting a subclass of LinearLayout in works fine, but to future proof things, I do it this way.
            LinearLayout linearLayout = new LinearLayout(measuringActivity = this);
            LinearLayout.LayoutParams matchParent = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            MeasureFrameLayout measureFrameLayout = new MeasureFrameLayout(this);
            measureFrameLayout.setLayoutParams(matchParent);
            linearLayout.addView(measureFrameLayout);
            this.addContentView(linearLayout, matchParent);
            // measureFrameLayout will now request this second activity to finish, sending back the width.
        }
    }

    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data) {
        // Probably can never happen, but just in case.
        if (resultCode == RESULT_CANCELED) {
            finish();
            return;
        }
        int width = data.getIntExtra("Width", -3);
        // Width is now set to the precise available width, and a layout can now be created. 
        ...
    }

class MeasureFrameLayout extends FrameLayout {
    boolean finished = false;
    public MeasureFrameLayout(Context context) {
        super(context);
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (finished) {
            return;
        }
        finished = true;
        // Send the width back as the result.
        Intent data = new Intent().putExtra("Width", MeasureSpec.getSize(widthMeasureSpec));
        MainActivity.measuringActivity.setResult(Activity.RESULT_OK, data);
        // Tell the (second) activity to finish.
        MainActivity.measuringActivity.finish();
    }
}    

科特林牌手表

fun getScreenHeight(activity: Activity): Int {
    val metrics = DisplayMetrics()
    activity.windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.heightPixels
}

fun getScreenWidth(activity: Activity): Int {
    val metrics = DisplayMetrics()
    activity.windowManager.defaultDisplay.getMetrics(metrics)
    return metrics.widthPixels
}

JAVA

DisplayMetrics dimension = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dimension);
int w = dimension.widthPixels;
int h = dimension.heightPixels;