我创建了一些自定义元素,并希望以编程方式将它们放置在右上角(距离上边缘n个像素,距离右边缘m个像素)。因此,我需要获得屏幕宽度和屏幕高度,然后设置位置:
int px = screenWidth - m;
int py = screenHeight - n;
如何在主活动中获取screenWidth和screenHeight?
我创建了一些自定义元素,并希望以编程方式将它们放置在右上角(距离上边缘n个像素,距离右边缘m个像素)。因此,我需要获得屏幕宽度和屏幕高度,然后设置位置:
int px = screenWidth - m;
int py = screenHeight - n;
如何在主活动中获取screenWidth和screenHeight?
当前回答
(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的用户,但这就是我们剩下的。
其他回答
我使用了上述建议,并为我们的问题创建了一个kotlin版本。希望这为使用科特林的人提供一些额外的帮助:
private val screenDimensions: Int by lazy {
val display = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
Point()
.also { size ->
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> display.getRealSize(size)
else -> display.getSize(size)
}
}
}
screenDimensions.x // width
screenDimensions.y // height
查找屏幕的宽度和高度:
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);
}
在Kotlin要简单得多。
val displayMetrics = Resources.getSystem().displayMetrics
displayMetrics.heightPixels
displayMetrics.widthPixels
对于正在搜索没有状态栏和操作栏的可用屏幕尺寸的用户(也感谢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);
}
在活动的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();
}
}