Làm thế nào để có được kích thước màn hình Android lập trình, một lần và mãi mãi?


132

Làm cách nào tôi có thể tìm ra kích thước màn hình của mình theo chương trình, trong các đơn vị được sử dụng bởi các sự kiện chạm và Xem đo / bố cục? Nói cách khác, tôi muốn tọa độ của góc dưới bên phải của màn hình, trong hệ thống tọa độ được sử dụng bởi các sự kiện chạm ' getRawX()/getRawY()View.getLocationOnScreen().

Tôi ngần ngại gọi các đơn vị sự kiện / chế độ xem mong muốn là "pixel" vì rõ ràng có một số khái niệm "pixel" trên điện thoại của tôi ở nhiều chế độ khác nhau và chúng không thêm vào một câu chuyện nhất quán.

Tôi thấy điều này đã được hỏi và trả lời rất nhiều trên stackoverflow và các nơi khác, nhưng không có câu trả lời nào thực sự hoạt động trên điện thoại của tôi (droid 4, android 4.1.2) trong tất cả các chế độ:

(wow!)

Mã này dành cho mã thư viện cần hoạt động bất kể ứng dụng có ở "chế độ tương thích màn hình" hay không (ví dụ: targetSdkVersion <= 10 trong bảng kê khai) hay không và tôi cũng không muốn đưa ra bất kỳ giả định nào về vị trí, kích thước hoặc sự tồn tại của thanh trạng thái hoặc bất kỳ trang trí màn hình tương tự nào khác.


Dưới đây là sự thật:

  1. điện thoại của tôi (một droid 4 chạy Android 4.1.2) có các pixel vật lý 540x960, tức là các chấm phát sáng ít màu.

  2. kích thước của màn hình trong các đơn vị mong muốn, từ việc xem các sự kiện chạm và Xem số đo, là 360x640 khi ứng dụng ở chế độ tương thích màn hình, 540x960 khi ứng dụng không ở chế độ tương thích màn hình. Đây là những con số tôi cần tìm theo chương trình, không có các sự kiện chạm hoặc Lượt xem để tìm chúng, nhưng tôi gặp khó khăn rất lớn trong việc tìm kiếm bất kỳ API nào sẽ trả về những con số này.

  3. Các đối tượng Display và DisplayMetrics thu được theo nhiều cách khác nhau đều cho rằng kích thước màn hình là 540x960 "pixel" (cho dù ở chế độ tương thích màn hình hay không). Cụ thể, tất cả những điều sau đây đều nói 540x960 mọi lúc: DisplayMetrics. {Width, height} Pixels, Display.getSize (), Display.getRealSize (), Display.get {Width, height} (),

  4. Các đối tượng cấu hình thu được theo nhiều cách khác nhau đều nói màn hình {Width, height} Dp = 360x614 (cho dù ở chế độ compat màn hình hay không). Tôi không tin rằng đại diện cho toàn bộ màn hình, vì tỷ lệ khung hình là sai. (Tôi nghĩ đó là toàn bộ màn hình trừ thanh trạng thái; tôi cần toàn bộ màn hình.) Tôi nghĩ rằng toàn bộ màn hình là 360x640 dp, mặc dù tôi không biết bất kỳ API nào trả về 640 đó.

  5. DisplayMetrics thu được theo nhiều cách khác nhau cho biết "mật độ" là 1.0f khi ở chế độ compat màn hình, 1.5f khi không ở chế độ compat màn hình.

  6. Các hoạt động getWindow().getAttributes().{width,height} không hữu ích vì nó thường chứa MATCH_PARENT thay vì kích thước thực tế. Nhưng tôi rõ ràng có thể nhận được câu trả lời mong muốn từ một của hoạt động getWindow().getDecorView().getMeasured{Width,Height}() (được thực sự ngạc nhiên kể từ decorView cửa sổ của của hoạt động không giống như nó chiếm toàn bộ màn hình, nó trông giống như nó chiếm màn hình trừ đi thanh trạng thái). Nhưng tôi không muốn dựa vào điều này bởi vì nếu cửa sổ bị thay đổi kích thước (bàn phím mềm xuất hiện? Ai đó đang gọi window.setAttribut ()? Hoặc có thể tôi hoàn toàn không tham gia Hoạt động), đây rõ ràng sẽ là tất cả Sai lầm.

Tôi hiểu công thức sau đây được cho là giữ: pixel = dp * mật độ Có vẻ như đồng ý với tất cả các số được báo cáo ((3), (4), (5) ở trên) khi không ở chế độ tương thích màn hình: 540x960 = 360x640 * 1.5 Nhưng trong chế độ tương thích màn hình, nó không tăng thêm: 540x960! = 360x640 * 1 Vì vậy, có gì đó không ổn.

Tôi nghĩ rằng lời giải thích đơn giản nhất là các phương pháp được liệt kê trong (3) ở trên chỉ đơn giản là đưa ra câu trả lời sai cho "pixel" khi ở chế độ tương thích màn hình - nghĩa là chúng có ý định trả về 360x640 "pixel" nhưng chúng bị sai trả lại 540x960 thay thế. Nhưng có thể có những cách khác để xem xét nó.

Trong mọi trường hợp, có được các số mong muốn bất kể chế độ, từ các mảnh ghép ở trên, chắc chắn là một câu đố khó khăn. Tôi đã tìm thấy một cách có vẻ như hoạt động trên điện thoại của mình ở cả hai chế độ, nhưng nó cực kỳ mạch lạc và nó dựa trên hai giả định vẫn có vẻ khá run (như được mô tả trong các nhận xét mã bên dưới).

Đây là công thức của tôi:

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

Có cách nào tốt hơn / sạch hơn để tìm kích thước của màn hình không ??


29
+1 Câu hỏi tuyệt vời, và cho thấy rất nhiều nỗ lực nghiên cứu.
Alex Gittemeier

1
@Don Trong tài liệu , giải thích rằng chế độ tương thích sẽ ngừng thực hiện thao tác "thu phóng để phù hợp" với các thiết lập cũ hơn. Tuy nhiên, nó không được giải thích rõ ràng "cách thức hoạt động", từ quan sát của bạn, tôi nghĩ rằng họ chỉ đơn giản là tắt tỷ lệ mật độ, tức là: 1px trở thành 1dp. Có thể là thay đổi này chỉ nằm trong phần kết xuất và DisplayMetricskhông bao giờ được cập nhật các thay đổi đó. Có những vấn đề như thế này đã được nộp.
SD

@ người dùng 117 - thú vị. Vâng một phần của DisplayMetrics đã được cập nhật tại mật độ least-- thay đổi đến 1.0. Nhưng widthPixels / heightPixels đã không được thay đổi để phù hợp, có vẻ như. Về vấn đề được trích dẫn, có vẻ như hành vi được hoàn nguyên về hành vi 3.1 (tức là tôi đang thấy heightPixels bao gồm thanh trạng thái ... nhưng có vẻ như trong các đơn vị sai)
Don hatch

@DonHatch Cảm ơn, vui lòng - Tôi thực sự đang cố gắng khen ngợi một câu hỏi chu đáo thuộc loại lạ lùng không được chào đón trên StackExchange - lưu ý rằng câu hỏi nhiều hơn "thực" không có gì trong câu trả lời, nói về (thấp) ) chất lượng kiến ​​thức của khán giả về chủ đề này. Bây giờ, tôi có thể bị tổn thương bởi những câu hỏi của chính mình bị đóng hết lần này đến lần khác vì "không có thật", và cảm giác hài hước có thể làm tôi thất vọng, nhưng nó bắt đầu giống như những câu hỏi mà câu trả lời "dễ chịu" thực sự tất cả những gì trở thành ở đây ... Và tất nhiên, tôi đã nâng cấp của bạn :)
mlvljr

btw! Đây là một cái gì đó dọc theo những nghi ngờ của tôi: michael.richter.name/bloss/ ((xem đặc biệt (1) điểm của anh ấy, một trong những câu trả lời được đưa ra nhanh chóng - thực sự chỉ là trường hợp với Q này!). Chúc mừng NY, dù sao đi nữa (của tôi đến trong 11 phút)! :)
mlvljr

Câu trả lời:


41
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

Bây giờ bạn có thể đo kích thước màn hình của mình bằng pixel, đơn vị đo tốt hơn centimet vì tất cả các nút, xem văn bản, v.v. đều được đo bằng đơn vị này. Đó là những gì tôi sử dụng bình thường


3
Theo Op (điểm số 3 cụ thể), điều này có sai ở chế độ tương thích màn hình không?
Tom

9

Bằng cách sử dụng DisplayMetrics, bạn có thể nhận được chiều cao và chiều rộng của màn hình của bất kỳ thiết bị nào. Lưu ý rằng chiều rộng và chiều cao rất nhạy cảm với xoay. đây là mã

DisplayMetrics metrics; 
int width = 0, height = 0;

Trong phương pháp onCreate của bạn

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

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

Thử cái này.


2
Không, như tôi đã nói trong (3), số liệu. {width, height} Pixels không đưa ra câu trả lời đúng khi ở chế độ tương thích màn hình.
Don nở

Ngoài ra tôi phát hiện ra: Có vẻ như số liệu lite.heightPixels có thể cho chiều rộng trong trường hợp màn hình được xoay và ngược lại!
JohnyTex

8

Trong số 6 của bạn, bạn lưu ý rằng DecorView dường như cung cấp những gì bạn muốn, nhưng bạn không nghĩ rằng nó là có thể thực hiện được. Tôi tin rằng đó là gần như bạn có thể đến. Theo tài liệu cho Window.getDecorView:

Truy xuất chế độ xem trang trí cửa sổ cấp cao nhất (chứa khung / trang trí cửa sổ tiêu chuẩn và nội dung của khách hàng bên trong đó), có thể được thêm dưới dạng cửa sổ cho trình quản lý cửa sổ.

Thanh trạng thái là một phần của trang trí cửa sổ được đề cập ở đó. Bàn phím phần mềm và các lớp phủ khác sẽ nhận được cửa sổ riêng, vì vậy chúng không nên can thiệp vào các giá trị liên quan. Đúng là không chính xác các số liệu hiển thị, nhưng nếu ứng dụng của bạn ở chế độ toàn màn hình thì nó phải luôn là kích thước toàn màn hình được lọc thông qua trình dịch tương thích. Các ứng dụng khác sẽ không có quyền truy cập vào ứng dụng của bạn Window, vì vậy không cần phải lo lắng về việc một số ứng dụng khác thay đổi các thuộc tính trong khi bạn không tìm kiếm.

Mong rằng sẽ giúp.


5

Tôi nên đặt nó như một bình luận nhưng tôi không có đại diện cho điều đó.
Đây có thể không phải là một câu trả lời hoàn toàn chính xác nhưng tôi đã nhận được kích thước của mình khi tôi chuyển đổi chiều cao và chiều rộng trong phương thức DisplayMetrics.

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

như tôi đã nói điều này có thể không đúng nhưng tôi không biết tại sao nhưng nó hiệu quả với tôi.


Điều này là do màn hình của bạn đã xoay tôi tin.
JohnyTex

Nó không tin tôi.
abhyudayasrinet


3

Tôi đã sử dụng định lý Pythagoras để tìm kích thước đường chéo của màn hình điện thoại / máy tính bảng Android, cùng một nguyên tắc có thể được áp dụng cho màn hình iPhone hoặc Blackberry.

DisplayMetrics met = new DisplayMetrics();                
this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
String strSize = 
new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
(met.widthPixels / met.xdpi)) +
((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
// using Dots per inches with width and height

Pythagoras hẳn là một bộ gen, anh biết lập trình điện thoại thông minh từ nhiều năm trước: p


1

Tôi sử dụng phương pháp dưới đây để có được chiều rộng của thiết bị:

public static int getDeviceWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    int width=display.getWidth();
    return width;
}

Phương pháp này không được chấp nhận. Vui lòng sử dụng phương pháp displaymetrics.
Simon

0

Tôi nghĩ rằng chức năng này sẽ giúp bạn chỉ đơn giản là có được chiều rộng và chiều cao của kích thước màn hình Android của bạn. Hàm trả về chiều rộng và chiều cao dưới dạng một mảng các số nguyên như dưới đây

private int[] getScreenSIze(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int h = displaymetrics.heightPixels;
        int w = displaymetrics.widthPixels;

        int[] size={w,h};
        return size;

    }

và trên phương thức tạo của bạn xuất ra chiều rộng và chiều cao của bạn như được hiển thị bên dưới

 int[] screenSize= getScreenSIze();
        int width=screenSize[0];
        int height=screenSize[1];
        screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);

Tải về mã nguồn và kiểm tra nó trên studio android của bạn


0

Điều này làm việc cho tôi:

int width = Resources.getSystem (). getDisplayMetrics (). widthPixels;

int height = Resources.getSystem (). getDisplayMetrics (). heightPixels;

Tôi đã sử dụng điều này để cập nhật chiều rộng của các mục của mình trong chế độ xem tái chế ngang. (Theo yêu cầu của tôi) Hy vọng nó sẽ giúp được ai đó!


-1

Đối với giải pháp này trong Kotlin , hãy thử điều này:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.