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

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


如何在主活动中获取screenWidthscreenHeight

评论

使用dp而不是px。因为它会扭曲您与其他设备的布局。.

不要忘了用getResources()。getDisplayMetrics()。density乘以显示比例缩放

这证明投票最多的答案并不总是最好的(很多人为代表重复答案)。尝试使用Balaji.K的getMetrics,而不是getSize和已弃用的getWidth / getHeight组合(忽略错误)。 Nik在其答案中的评论甚至解释了getDisplayMetrics来考虑系统/状态栏的大小。同样,您也可以将密度用作jmaculate,并把LoungeKatt解释为具有EXACT值:DisplayMetrics dm = getResources()。getDisplayMetrics(); float fwidth = dm.density * dm.widthPixels;经过Android v2.2(API 8)和v4.0的测试,结果良好,没有错误/警告。

DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager()。getDefaultDisplay()。getMetrics(displaymetrics); int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels;

获取DisplayMetrics的另一种方法:Resources.getSystem()。getDisplayMetrics()。您不需要上下文即可获取它们。

#1 楼

如果要以像素为单位显示尺寸,可以使用getSize
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

如果不在Activity中,则可以通过Display获得默认的WINDOW_SERVICE
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

如果在一个片段中,要完成此操作,只需使用Activity.WindowManager(在Xamarin.Android中)或getActivity()。getWindowManager()(在Java中)。
在引入getSize之前(API级别13),您可以使用现在不建议使用的getWidthgetHeight方法:
Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();  // deprecated
int height = display.getHeight();  // deprecated

对于您要描述的用例,布局中的边距/填充似乎更合适。
另一种方法是:DisplayMetrics

描述有关显示器的一般信息的结构,例如其大小,密度和字体缩放。要访问DisplayMetrics成员,请像这样初始化一个对象:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

我们可以使用widthPixels获取以下信息:

“像素。“

示例:
Log.d("ApplicationTagName", "Display width in px is " + metrics.widthPixels);

Api 30级更新
final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
 // Gets all excluding insets
 final WindowInsets windowInsets = metrics.getWindowInsets();
 Insets insets = windowInsets.getInsetsIgnoreVisibility(WindowInsets.Type.navigationBars()
         | WindowInsets.Type.displayCutout());

 int insetsWidth = insets.right + insets.left;
 int insetsHeight = insets.top + insets.bottom;

 // Legacy size that Display#getSize reports
 final Rect bounds = metrics.getBounds();
 final Size legacySize = new Size(bounds.width() - insetsWidth,
         bounds.height() - insetsHeight);


评论


getWidth()或getSize()?如果我需要我的应用程序在API <13和API> 13上运行,该怎么办?

–卡罗尔
2012年4月1日下午5:29

尝试{display.getSize(size);宽度= size.x;高度= size.y; } catch(NoSuchMethodError e){width = display.getWidth();高度= display.getHeight(); }

– Arnaud
2012年5月12日11:41



我不明白您为什么要使用try / catch进行此类检查?为什么不简单地使用if(android.os.Build.VERSION.SDK_INT> = 13)而根本不引发任何异常?我认为在正常的应用程序流中尝试/捕获是一种不好的做法。

–帕特里克(Patrik)
2012年11月28日15:41

@ A-Live,则该应用程序也会损坏(但不会崩溃)。但是,我们的开发人员必须预先检查新的os版本,这可能只是掩盖了问题。同样,使用此参数,可以/应该用try / catch包围每几行代码,在我看来,这已经是不好的做法了。

–帕特里克(Patrik)
2012-12-30 10:16



如果要获得除导航栏和/或通知栏以外的屏幕尺寸怎么办

– Android开发人员
13年5月12日在23:24

#2 楼

一种方法是:
Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();
int height = display.getHeight();

已弃用,您应该尝试以下代码。前两行代码为您提供DisplayMetrics objecs。该对象包含heightPixelswidthPixels之类的字段。
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
      
int height = metrics.heightPixels;
int width = metrics.widthPixels;

Api 30级更新
final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
 // Gets all excluding insets
 final WindowInsets windowInsets = metrics.getWindowInsets();
 Insets insets = windowInsets.getInsetsIgnoreVisibility(WindowInsets.Type.navigationBars()
         | WindowInsets.Type.displayCutout());

 int insetsWidth = insets.right + insets.left;
 int insetsHeight = insets.top + insets.bottom;

 // Legacy size that Display#getSize reports
 final Rect bounds = metrics.getBounds();
 final Size legacySize = new Size(bounds.width() - insetsWidth,
         bounds.height() - insetsHeight);


评论


请注意,度量标准(宽度,高度)根据设备的旋转而变化。

–陈百强
2011-11-28 2:17

指标将返回显示的大小,但是由于系统栏的原因,HoneyComb及以上版本的活动空间将小于返回的空间。

–人
2011年12月29日上午11:12

@Guy,这取决于您的实现。您可以隐藏状态栏:requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow()。setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

– Hagai L
2012年3月28日上午11:00

也以这种方式存在:getContext()。getResources()。getDisplayMetrics()。widthPixels

–尼克
2012年7月11日下午5:32

最终浮动比例= getResources()。getDisplayMetrics()。density; int width =(int)(metrics.widthPixels *比例+ 0.5f); -这样做时必须考虑设备密度。

–废弃的购物车
2014年2月20日4:45



#3 楼

它可能无法回答您的问题,但了解(当我遇到此问题时我自己也在寻找它)可能有用,如果您需要一个View的尺寸,但是在尚未布局其布局时正在执行代码(例如,在onCreate()中),您可以使用ViewTreeObserver.OnGlobalLayoutListener设置View.getViewTreeObserver().addOnGlobalLayoutListener(),并将需要视图尺寸的相关代码放在此处。布局完成后,将调用侦听器的回调。

评论


或只是写view.post

–卢卡斯·哈纳塞克(Lukas Hanacek)
2013年9月19日上午9:27

view.post不能保证正常工作。这只是一个解决方法。

– marsbear
2014-02-25 14:31

@marsbear在哪里说不能保证View.post()工作?我很好奇,因为我也依靠这种方法在布局后获取View的大小,并且没有意识到它不可靠。

–陈百强
2014年3月22日,0:20

@Turbo我说:p我们之前使用过这种解决方法,结果证明它是不可靠的。该解决方法基于以下假设:初始布局是在与初始化相同的UIThread内完成的。因此,您可以通过post()将代码安排在下一个UI之前运行,并且很好。事实证明,在某些情况下布局可能会花费更长的时间,并且在发布的代码运行时视图仍未布局。我现在要做的是在onCreate中添加ViewTreeObserver,并在第一个onLayout之后将其删除。在第一个onLayout期间初始化您的东西。

– marsbear
2014年3月28日15:30



@marsbear从哪个视图中获取ViewTreeObserver无关紧要?还是他们都共享同一个人?

–陈百强
2014年4月9日在20:58

#4 楼

(2012年的答案,可能已经过时)如果要支持蜂窝前版本,则需要在API 13之前实现向后兼容性。类似:

int measuredWidth = 0;
int measuredHeight = 0;
WindowManager w = getWindowManager();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    Point size = new Point();
    w.getDefaultDisplay().getSize(size);
    measuredWidth = size.x;
    measuredHeight = size.y;
} else {
    Display d = w.getDefaultDisplay();
    measuredWidth = d.getWidth();
    measuredHeight = d.getHeight();
}


当然,不推荐使用的方法将最终从最新的SDK中删除,但是尽管我们仍然依赖大多数拥有Android 2.1、2.2和2.3的用户,但这仍然是我们的选择。

评论


是的,那是在2012年。

–digiphd
15年6月22日在22:46

抱歉,请允许我阐明我的意思。截至2015年6月22日,几乎没有人会支持API <14

– sudocoder
2015年6月23日在4:24



#5 楼


评论


这是这里唯一考虑到窗户装饰(状态栏/菜单栏)的帖子。对我来说很棒。

–安迪·科克伦(Andy Cochrane)
13年5月31日在20:24

太棒了,但是您永远都不会期望有业务逻辑触发异常。异常触发(即使捕获)对于性能来说也是可怕的。另外,如果SDK_INT> 13,则您的工作量超出了需要。相反,您应该在Build.VERSION.SDK_INT上添加一些if。

– Erik B
13年6月21日在23:15

@Erik B,我同意。我添加了改进的版本。我还是保留了“自SDK 1起”的部分,以防万一在try / catch中出了问题(我在Android上看到了很多不好的地方,尤其是当您认为不可能出问题的时候,所以我想确保它的安全:)) 。无论如何,不​​应有太多的开销,因为此计算仅应执行一次(例如,值可以保留在某些静态属性中)。

– DraganMarjanović
13年6月22日在16:41

请注意,此代码已获得GPL v3的许可,这可能会影响在生产应用中使用。

–TalkLittle
13年8月12日在2:00

GPL并依靠反射来调用将来的Android版本中可能不存在的方法。 h

–米歇尔
2015年11月14日15:41

#6 楼

最简单的方法:

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


#7 楼

要访问Android设备状态栏的高度,我们更喜欢采用编程方式来获取它:
示例代码
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
    result = getResources().getDimensionPixelSize(resId);
}
result给出像素的高度。
要快速访问

有关Title barNavigation barContent View的高度的更多信息,请查看Android设备屏幕尺寸。

评论


正是我需要的! getResources()。getDisplayMetrics()。heightPixels +结果给出实际的全屏高度。 DraganMarjanović的答案也有效,但我更喜欢这种更短,更简单的解决方案。

–米歇尔
2015年11月14日15:35



从Android Marshmallow开始,这种方法已经过时了。状态栏的高度可以从设备或Android版本更改。最好使用OnApplyWindowInsetsListener。

–海因里希
16-2-21在13:20

#8 楼

首先获取视图(例如,通过findViewById()),然后可以在视图本身上使用getWidth()。

评论


实际上,这就是文档告诉您的方式……但是,如果您不使用视图,那是毫无意义的。您可能正在使用其他内容,例如mglsurfaceview。

– gcb
2010-11-20 2:22

这样做更好,因为父视图可能不是显示器的大小。但请确保在要查询的视图的视图已被布局的位置上完成此操作,该视图通常不在onCreate()内。您可以使用onWindowFocusChanged(boolean hasFocus)中的自定义回调,在对所有视图进行测量之后,将调用该回调,以此类推,以确保您不会对感兴趣的视图收到不正确的尺寸...

–多里
2011年3月1日13:02

#9 楼

我有两个功能,一个用于发送上下文,另一个用于获取高度和宽度(以像素为单位):

public static int getWidth(Context mContext){
    int width=0;
    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    if(Build.VERSION.SDK_INT>12){
        Point size = new Point();
        display.getSize(size);
        width = size.x;
    }
    else{
        width = display.getWidth();  // Deprecated
    }
    return width;
}




public static int getHeight(Context mContext){
    int height=0;
    WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    if(Build.VERSION.SDK_INT>12){
        Point size = new Point();
        display.getSize(size);
        height = size.y;
    }
    else{
        height = display.getHeight();  // Deprecated
    }
    return height;
}


评论


您需要在函数签名上方添加@SuppressLint(“ NewApi”)才能进行编译。

–阿迪尔·马利克(Adil Malik)
13-10-14在15:09

我认为最好一口气获得高度和宽度,而不是单独调用API,因为否则它们可能会不同步。如果在运行代码时屏幕方向发生变化,则可能会发生这种情况。

–山姆
2015年5月26日下午5:50

#10 楼

为了使用XML动态缩放,有一个名为“ android:layout_weight”的属性。

下面的示例是根据synic在该线程上的响应进行修改的,显示的按钮占据了屏幕的75%(weight =。 25)和文本视图占据屏幕的剩余25%(权重= .75)。

<LinearLayout android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight=".25"
        android:text="somebutton">

    <TextView android:layout_width="fill_parent"
        android:layout_height="Wrap_content"
        android:layout_weight=".75">
</LinearLayout>


#11 楼

这是我用于该任务的代码:

// `activity` is an instance of Activity class.
Display display = activity.getWindowManager().getDefaultDisplay();
Point screen = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    display.getSize(screen);
} else {            
    screen.x = display.getWidth();
    screen.y = display.getHeight();
}


看起来足够干净,但是请注意不要使用。

#12 楼

这不是更好的解决方案吗? DisplayMetrics包含您需要的所有内容,并且可以从API 1运行。

public void getScreenInfo(){
    DisplayMetrics metrics = new DisplayMetrics();
    getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);

    heightPixels = metrics.heightPixels;
    widthPixels = metrics.widthPixels;
    density = metrics.density;
    densityDpi = metrics.densityDpi;
}


您还可以获取实际的显示(包括屏幕装饰,例如状态栏或软件导航栏)。使用getRealMetrics,但这仅适用于17+。

我是否缺少某些内容?

评论


这不会减少屏幕上控件的空间(例如Tablet或Nexus设备上的空间)。此外,我在10英寸平板电脑上获得的值也不同(750对800),具体取决于计算完成后“活动”是否处于活动状态。但是就我的目的而言,这还不错。谢谢!

–史蒂文·L
13-10-10在1:38



#13 楼

只是增加弗朗切斯科的答案。如果您想查找窗口中的位置或屏幕中的位置,则另一个更合适的观察者是
ViewTreeObserver.OnPreDrawListener()

这也可以用于查找以下项的其他属性在onCreate()时几乎未知的视图,例如滚动位置,缩放位置。

#14 楼

在Activity中使用以下代码。

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int wwidth = metrics.widthPixels;


#15 楼

查找屏幕的宽度和高度:

width = getWindowManager().getDefaultDisplay().getWidth();
height = getWindowManager().getDefaultDisplay().getHeight();


使用此工具,我们可以获得最新的SDK 13及更高版本。

// New width and height
int version = android.os.Build.VERSION.SDK_INT;
Log.i("", " name == "+ version);
Display display = getWindowManager().getDefaultDisplay();
int width;
if (version >= 13) {
    Point size = new Point();
    display.getSize(size);
    width = size.x;
    Log.i("width", "if =>" +width);
}
else {
    width = display.getWidth();
    Log.i("width", "else =>" +width);
}


#16 楼

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


#17 楼

我发现这可以解决问题。

Rect dim = new Rect();
getWindowVisibleDisplayFrame(dim);


评论


很酷,但是在源代码中关于此方法的一件令人恐惧的事情:此注释

–诺伯特
2012年7月19日在8:48



#18 楼

需要说的是,如果您不在Activity中,而是在View中(或在您的范围内具有View类型的变量),则无需使用WINDOW_SERVICE。然后,您至少可以使用两种方式。 >
我们不赞成在这里使用的所有这些方法。

#19 楼

public class AndroidScreenActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        String str_ScreenSize = "The Android Screen is: "
                                   + dm.widthPixels
                                   + " x "
                                   + dm.heightPixels;

        TextView mScreenSize = (TextView) findViewById(R.id.strScreenSize);
        mScreenSize.setText(str_ScreenSize);
    }
}


#20 楼

要获取屏幕尺寸,请使用显示指标

DisplayMetrics displayMetrics = new DisplayMetrics();
if (context != null) 
      WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
      Display defaultDisplay = windowManager.getDefaultDisplay();
      defaultDisplay.getRealMetrics(displayMetrics);
    }


以像素为单位获取高度和宽度

int width  =displayMetrics.widthPixels;
int height =displayMetrics.heightPixels;


#21 楼

这不是OP的答案,因为他希望显示尺寸以实像素为单位。我想要“设备独立像素”中的尺寸,然后将答案汇总在这里https://stackoverflow.com/a/17880012/253938和此处https://stackoverflow.com/a/6656774/253938与此:

    DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
    int dpHeight = (int)(displayMetrics.heightPixels / displayMetrics.density + 0.5);
    int dpWidth = (int)(displayMetrics.widthPixels / displayMetrics.density + 0.5);


#22 楼

您可以使用:

getResources().getDisplayMetrics().heightPixels;


来获取高度大小,而使用

getResources().getDisplayMetrics().widthPixels; 

来获取宽度大小。

#23 楼

有一种使用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;


#24 楼

我将这样包装getSize代码:

@SuppressLint("NewApi")
public static Point getScreenSize(Activity a) {
    Point size = new Point();
    Display d = a.getWindowManager().getDefaultDisplay();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        d.getSize(size);
    } else {
        size.x = d.getWidth();
        size.y = d.getHeight();
    }
    return size;
}


评论


这在运行Android 4.0(API 14)的模拟器上崩溃。

– jww
2014年9月5日在18:31



#25 楼

对于谁在没有状态栏和操作栏的情况下搜索可用的屏幕尺寸(也要感谢Swapnil的回答):

DisplayMetrics dm = getResources().getDisplayMetrics();
float screen_w = dm.widthPixels;
float screen_h = dm.heightPixels;

int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
    screen_h -= getResources().getDimensionPixelSize(resId);
}

TypedValue typedValue = new TypedValue();
if(getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true)){
    screen_h -= getResources().getDimensionPixelSize(typedValue.resourceId);
}


#26 楼

首先加载XML文件,然后编写以下代码:

setContentView(R.layout.main);      
Display display = getWindowManager().getDefaultDisplay();
final int width = (display.getWidth());
final int height = (display.getHeight());


根据屏幕分辨率显示宽度和高度。

#27 楼

请遵循以下方法:

public static int getWidthScreen(Context context) {
    return getDisplayMetrics(context).widthPixels;
}

public static int getHeightScreen(Context context) {
    return getDisplayMetrics(context).heightPixels;
}

private static DisplayMetrics getDisplayMetrics(Context context) {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    wm.getDefaultDisplay().getMetrics(displayMetrics);
    return displayMetrics;
}


#28 楼

科特林
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
}


#29 楼

有时候,在活动的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();
    }
}    


评论


显然,您也可以将捆绑包中的高度也传递回来。

–史蒂夫·沃林(Steve Waring)
13年5月22日在12:21

#30 楼

如果您不希望WindowManagers,Points或Displays产生开销,则可以将XML中最顶层View项的height和width属性获取,只要将其高度和宽度设置为match_parent。 (只要布局占据了整个屏幕,这就是事实。)例如,如果您的XML以这样的开头:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/entireLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >


然后findViewById(R.id.entireLayout).getWidth()将返回屏幕的宽度,而findViewById(R.id.entireLayout).getHeight()将返回屏幕的高度。