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

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

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


当前回答

•Kotlin版本通过扩展属性

在android中有多种实现屏幕尺寸的方法,但我认为最好的解决方案可以独立于Context实例,因此您可以在代码中的任何地方使用它。在这里,我通过kotlin扩展属性提供了一个解决方案,它可以很容易地知道以像素为单位的屏幕大小以及dp:


尺寸Utils.kt

import android.content.res.Resources
import android.graphics.Rect
import android.graphics.RectF
import android.util.DisplayMetrics
import kotlin.math.roundToInt

/**
 * @author aminography
 */

private val displayMetrics: DisplayMetrics by lazy { Resources.getSystem().displayMetrics }

val screenRectPx: Rect
    get() = displayMetrics.run { Rect(0, 0, widthPixels, heightPixels) }

val screenRectDp: RectF
    get() = displayMetrics.run { RectF(0f, 0f, widthPixels.px2dp, heightPixels.px2dp) }

val Number.px2dp: Float
    get() = this.toFloat() / displayMetrics.density

val Number.dp2px: Int
    get() = (this.toFloat() * displayMetrics.density).roundToInt()


用法:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val widthPx = screenRectPx.width()
        val heightPx = screenRectPx.height()
        println("[PX] screen width: $widthPx , height: $heightPx")

        val widthDp = screenRectDp.width()
        val heightDp = screenRectDp.height()
        println("[DP] screen width: $widthDp , height: $heightDp")
    }
}

结果:

当设备处于纵向时:

[PX] screen width: 1440 , height: 2392
[DP] screen width: 360.0 , height: 598.0

当设备处于横向时:

[PX] screen width: 2392 , height: 1440
[DP] screen width: 598.0 , height: 360.0


如果您不是kotlin的粉丝,请使用java版本:

import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.DisplayMetrics;

/**
 * @author aminography
 */
public class DimensionUtils {

    private static DisplayMetrics displayMetrics;

    private static DisplayMetrics getDisplayMetrics() {
        if (displayMetrics == null) {
            displayMetrics = Resources.getSystem().getDisplayMetrics();
        }
        return displayMetrics;
    }

    public static Rect screenRectPx() {
        return new Rect(0, 0, getDisplayMetrics().widthPixels, getDisplayMetrics().heightPixels);
    }

    public static RectF screenRectDp() {
        return new RectF(0f, 0f, px2dp(getDisplayMetrics().widthPixels), px2dp(getDisplayMetrics().heightPixels));
    }

    public static float px2dp(int value) {
        return value / getDisplayMetrics().density;
    }

    public static int dp2px(float value) {
        return (int) (value * getDisplayMetrics().density);
    }
}

其他回答

我会这样包装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;
}

我发现这起了作用。

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

这里是Kotlin实现中对上面一些答案的简单改编。它需要清单中如上所述的windowsSoftInput=“adjustResize”:

class KeyboardWatcher(private val layoutRooView: View) {

    companion object {
        private const val MIN_KEYBOARD_HEIGHT = 200f
    }

    private val displayMetrics: DisplayMetrics = layoutRooView.resources.displayMetrics
    private var stateVisible = false

    var observer: ((Boolean) -> Unit)? = null

    init {
        layoutRooView.viewTreeObserver.addOnGlobalLayoutListener {
            val heightDiff = layoutRooView.rootView.height - layoutRooView.height
            if (!stateVisible && heightDiff > dpToPx(MIN_KEYBOARD_HEIGHT)) {
                stateVisible = true
                observer?.invoke(stateVisible)
            } else if(stateVisible) {
                stateVisible = false
                observer?.invoke(stateVisible)
            }
        }
    }

    private fun dpToPx(valueInDp: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, displayMetrics)
    }
}

并使用:

val activityRootView = findViewById<ViewGroup>(R.id.activityRoot)
KeyboardWatcher(activityRootView).observer = { visible ->
    if (visible) do something here ...
}

查找屏幕的宽度和高度:

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);
}

我有两个函数,一个用于发送上下文,另一个用于获取像素的高度和宽度:

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;
}

and

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;
}