Android ekran boyutu programlı olarak nasıl elde edilir?


132

Dokunmatik olayların kullandığı birimlerde ve Ölçümü / düzeni görüntüle'de ekran boyutumu programlı olarak nasıl öğrenebilirim? Başka bir deyişle, dokunmatik olayların kullandığı koordinat sisteminde ekranın sağ alt köşesinin koordinatlarını istiyorum ' getRawX()/getRawY()ve View.getLocationOnScreen().

Telefonumda çeşitli modlarda birkaç "piksel" kavramı olduğu ve tutarlı bir hikaye eklemediği için, istenen olay / görüntüleme birimlerini "piksel" olarak adlandırmakta tereddüt ediyorum.

Bunun stackoverflow'da ve başka yerlerde çok sorulduğunu ve yanıtlandığını görüyorum, ancak yanıtların hiçbiri telefonumda (droid 4, android 4.1.2) tüm modlarda çalışmıyor:

(vay!)

Bu, uygulamanın "ekran uyumluluk modunda" (yani, bildirimde targetSdkVersion <= 10) olup olmadığına bakılmaksızın çalışması gereken kitaplık kodu içindir ve ayrıca konum, boyut hakkında herhangi bir varsayımda bulunmak istemiyorum veya durum çubuğunun veya diğer benzer ekran dekorasyonlarının varlığı.


İşte gerçekler:

  1. telefonumda (android 4.1.2 çalıştıran bir droid 4) 540x960 fiziksel piksel var, yani küçük renkli parlak noktalar.

  2. Dokunma olaylarına ve Görüntüleme ölçümlerine bakmadan istenen birimlerdeki ekranın boyutu, uygulama ekran uyumluluk modundayken 360x640, uygulama ekran uyumluluk modunda olmadığında 540x960'tır. Bunlar, dokunmatik olayları veya Görünümleri bulmak için uğraşmadan programlı olarak bulmam gereken sayılar, ancak bu sayıları döndürecek herhangi bir API bulmakta aşırı zorluk çekiyorum.

  3. Çeşitli yollarla elde edilen Display ve DisplayMetrics nesnelerinin tümü ekran boyutunun 540x960 "piksel" olduğunu iddia eder (ekran uyumlu modda olsun veya olmasın). Spesifik olmak gerekirse, aşağıdakilerin tümü her zaman 540x960 der: DisplayMetrics. {Width, height} Pixels, Display.getSize (), Display.getRealSize (), Display.get {Width, Height} (),

  4. Çeşitli şekillerde elde edilen yapılandırma nesnelerinin tümü ekran {Genişlik, Yükseklik} Dp = 360x614 (ekran uyumlu modda olsun veya olmasın) der. En boy oranı yanlış olduğu için bunun tüm ekranı temsil ettiğine inanmıyorum. (Sanırım tüm ekran eksi durum çubuğu; tüm ekrana ihtiyacım var.) Tüm ekranın 360x640 dp olduğunu söylemenin güvenli olduğunu düşünüyorum, ancak bu 640'ı döndüren herhangi bir API bilmiyorum.

  5. Çeşitli şekillerde elde edilen DisplayMetrics, ekran uyumlu moddayken "yoğunluğun" 1.0f, ekran uyumlu modda olmadığında 1.5f olduğunu söyler.

  6. Etkinlik getWindow().getAttributes().{width,height} , genellikle MATCH_PARENT gerçek boyutlardan ziyade içerdiği için yararlı değildir . Ama görünüşe göre istediğim cevabı bir aktiviteden alabiliyorum getWindow().getDecorView().getMeasured{Width,Height}() (bu aslında şaşırtıcı çünkü aktivitenin penceresinin decorView tüm ekranı kaplıyor gibi görünmüyor ; ekran eksi durum çubuğunu kaplıyor gibi görünüyor). Ancak buna güvenmek istemiyorum çünkü eğer pencere yeniden boyutlandırılırsa (ekran klavyesi görünüyor? Birisi window.setAttributes () 'ı arıyor mu? Veya belki de ben bir Aktivitede değilsem), açıkça hepsi bu olacak yanlış.

Aşağıdaki formülün tutması gerektiğini anlıyorum: piksel = dp * yoğunluk Ekran uyumluluk modunda olmadığında , bildirilen tüm sayılarla ((3), (4), (5) yukarıda) uyumlu görünüyor: 540x960 = 360x640 * 1.5 Ancak ekran uyumluluk modunda şu sonuç çıkmıyor: 540x960! = 360x640 * 1 Yani bir şeyler ters gidiyor.

Bence en basit açıklama, yukarıda (3) 'te listelenen yöntemlerin ekran uyumluluk modundayken basitçe "pikseller" için yanlış yanıt vermesidir - yani 360x640 "piksel" döndürmeleri amaçlanmıştır, ancak yanlıştır bunun yerine 540x960 döndürülüyor. Ama ona bakmanın başka yolları da olabilir.

Her durumda, yukarıdaki bulmaca parçalarından moddan bağımsız olarak istenen sayıları elde etmek kesinlikle zor bir bilmecedir. Telefonumda her iki modda da işe yarayan bir yol buldum, ancak son derece dolambaçlı ve hala oldukça titrek görünen iki varsayıma dayanıyor (aşağıdaki kod yorumlarında açıklandığı gibi).

İşte tarifim:

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

Ekranın boyutunu bulmanın daha iyi / temiz bir yolu var mı?


29
+1 Harika soru ve çok fazla araştırma çabası gösteriyor.
Alex Gittemeier

1
@Don Dokümanlarda , uyumluluk modunun eski kurulumlarda "sığdırmak için yakınlaştırma" işlemini durduracağı açıklanmıştır. Ancak "nasıl çalıştığı" net bir şekilde açıklanmadı, gözlemlerinize göre, sadece yoğunluk ölçeklendirmeyi kapattıklarını düşünüyorum, yani: 1px, 1dp olur. Bu değişiklik yalnızca oluşturma bölümünde olabilir ve DisplayMetricsbu tür değişikliklerden asla güncellenmez. Gibi sorunlar var bu zaten açtı.
SD

@ user117 - ilginç. Eh bölüm DisplayMetrics arasında 1.0 olarak değiştirildi least-- yoğunlukta güncellendi. Ama görünüşe göre widthPixels / heightPixels eşleşecek şekilde değiştirilmedi. Bahsedilen sorunla ilgili olarak, davranış 3.1 davranışına geri döndürülmüş gibi görünüyor (yani yükseklik Piksellerin durum çubuğunu içerdiğini görüyorum ... ama yanlış birimlerde görünüyor)
Don Hatch

@DonHatch Teşekkürler, nazikçe - Aslında StackExchange'de tuhaf bir şekilde hoş karşılanmayan düşünceli bir soruya övgü vermeye çalışıyordum - sorunun "gerçek" den daha fazlası olmasının yanıtlarda nasıl hiçbir şey almadığına dikkat edin. ) izleyicinin konuyla ilgili bilgilerinin kalitesi. Şimdi, kendi sorularımın "gerçek olmadığı" için birbiri ardına kapatılmasından travmatize olabilirim ve mizah duygusu beni hayal kırıklığına uğratıyor olabilir, ancak "güzel" tarif cevaplarının gerçekten olduğu sorular gibi görünmeye başlar. bütün bunlar burada ne oluyor ... Ve tabii ki, sizinkine oy verdim :)
mlvljr

Btw! işte şüphelerim doğrultusunda bir şey var: michael.richter.name/blogs/… (özellikle onun (1) noktasına bakın, hızlı hazırlanmış cevaplarla ilgili olan - aslında sadece bu Q'daki durum!). Mutlu NY, neyse (benimki 11 dakika içinde geliyor)! :)
mlvljr

Yanıtlar:


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

Artık ekran boyutunuzu piksel cinsinden ölçebilirsiniz, bu da santimetreden daha iyi bir ölçü birimi çünkü tüm düğmeler, metin görünümleri vb. Bu birimde ölçülmüştür. Normalde kullandığım şey


3
Operasyona göre (özellikle 3. nokta), ekran uyumluluk modunda bu yanlış olmaz mı?
Tom

9

DisplayMetrics'i kullanarak herhangi bir cihazın ekranının yüksekliğini ve genişliğini öğrenebilirsiniz. Genişlik ve yüksekliğin dönüşe duyarlı olduğunu unutmayın. işte kod.

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

OnCreate Yönteminizde

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

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

Bunu dene.


2
I (3), ölçümler. bahsedilen olarak hayır {genişlik, yükseklik} pikseldir olup , ekran uyumluluk modunda doğru cevap vererek.
Don Hatch

Ayrıca şunu keşfettim: Görünüşe göre lite metrics.heightPixels, ekranın döndürülmesi durumunda genişliği verebilir ve bunun tersi de geçerlidir!
JohnyTex

8

# 6'nızda, DecorView'ün istediğinizi sağladığını, ancak bunun gerçekçi olduğunu düşünmediğinizi not ediyorsunuz. Bunun gelebileceğin kadar yakın olduğuna inanıyorum. Belgelere göre Window.getDecorView:

Pencere yöneticisine bir pencere olarak eklenebilecek en üst düzey pencere dekor görünümünü (standart pencere çerçevesi / dekorasyonları ve bunun içindeki müşterinin içeriğini içerir) alın.

Durum çubuğu, orada bahsedilen pencere dekorasyonunun bir parçasıdır. Yazılım klavyeleri ve diğer kaplamalar kendi pencerelerini alacaklardır, bu nedenle ilgili değerlere müdahale etmemelidirler. Bunun tam olarak görüntü ölçümleri olmadığı doğrudur, ancak uygulamanız tam ekran ise, her zaman uyumluluk çevirmeni aracılığıyla filtrelenen tam ekran boyutu olmalıdır. Diğer uygulamaların uygulamanıza erişimi olmayacağından, Windowbaşka uygulamaların siz bakmıyorken özniteliklerini değiştirmesi konusunda endişelenmenize gerek yoktur.

Umarım yardımcı olur.


5

Bunu bir yorum olarak koymalıyım ama bunun için bir sayım yok.
Bu tamamen doğru bir cevap olmayabilir, ancak DisplayMetrics yönteminde yüksekliği ve genişliği değiştirdiğimde boyutlarımı aldım.

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

dediğim gibi bu doğru olmayabilir ama nedenini bilmiyorum ama benim için çalıştı.


Bunun nedeni, ekranınızın döndüğüne inanıyorum.
JohnyTex

Bana güvenmedi.
abhyudayasrinet

3

İçinde getRealMetrics ve getRealSize dışarı API seviyesini 17 veya daha yüksek çeki kullanıyorsanız Display

API seviyesi 14, 15 ve 16 için buraya bakın


3

Android telefon / tablet ekranının köşegen boyutunu bulmak için Pisagor teoremini kullandım, aynı prensip iPhone veya Blackberry ekranına da uygulanabilir.

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

Pisagor bir dahi olmalı, akıllı telefon programlamayı yıllar önce biliyordu: p


1

Cihazın genişliğini elde etmek için aşağıdaki yöntemi kullanıyorum:

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

Bu yöntem kullanımdan kaldırılmıştır. Lütfen displaymetrics yöntemini kullanın.
Simon

0

Bu işlevin, android ekran boyutunuzun genişliğini ve yüksekliğini elde etmenize yardımcı olacağını düşünüyorum. İşlev, genişliği ve yüksekliği aşağıda gösterildiği gibi bir tamsayı dizisi olarak döndürür

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;

    }

ve oluşturma yönteminizde, aşağıda gösterildiği gibi genişliğinizi ve yüksekliğinizi çıkarın

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

Kaynak kodunu indirin ve android stüdyonuzda test edin


0

Bu benim için çalışıyor:

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

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

Bunu, öğelerimin genişliğini yatay bir geri dönüşümcü görünümünde güncellemek için kullandım. (İhtiyacıma göre) Umarım birine yardımcı olur!


-1

Kotlin'deki bu çözüm için şunu deneyin:

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.