Android dan mengatur lebar dan tinggi secara terprogram dalam satuan dp

304

Aku melakukan:

button.setLayoutParams(new GridView.LayoutParams(65, 65));

Menurut dokumen, satuan untuk lebar dan tinggi (keduanya 65 di atas) adalah "piksel". Bagaimana Anda memaksakan ini menjadi piksel independen perangkat, atau "dp"?

SK9
sumber

Jawaban:

541

Anda harus mengonversinya dari dps ke piksel menggunakan faktor skala tampilan.

final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
Robby Pond
sumber
111
Konversi yang benar adalah (int) (skala dps * + 0,5f). Ini adalah formula yang kami gunakan di seluruh kerangka kerja.
Romain Guy
8
Rumusnya ada dalam dokumen. Untuk bacaan lebih lanjut, buka bagian 3 dari developer.android.com/guide/practices/…
SK9
34
@ DomainGuy, bisakah Anda menambahkan fungsi utilitas ke API untuk mengkonversi dari dpke px? Terima kasih.
AlikElzin-kilaka
3
apa dps di sini? im mendapatkan "dps tidak dapat diselesaikan ke variabel" kesalahan? apa jenis "dps" perlu menyatakan ??
Deepak
5
Variabel "dps" adalah nilai input yang ingin Anda konversi.
Robby Pond
233

Saya tahu ini adalah pertanyaan lama namun saya telah menemukan cara yang jauh lebih rapi dalam melakukan konversi ini.

Jawa

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());

Kotlin

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)
drspaceboo
sumber
8
Dilakukan dengan baik untuk mengetahui bagaimana melakukan ini. Saya bukan penggemar mengulangi formula di beberapa tempat! Terima kasih.
darrenp
2
Jika tidak, maka buat fungsi dengan rumus
Sayka
1
@ Kenobi Ini melakukan konversi untuk Anda dari DP ke PX. Di 65atas adalah nilai DP yang ingin Anda konversi ke PX
drspaceboo
7
Ini harus menjadi jawaban yang diterima, bukan yang sekarang di mana angka ini (0,5) datang secara ajaib dari mana
Johny19
1
@ Johny19 0,5 bukan sihir. Ini hanya bagaimana membulatkan angka floating point ke bilangan bulat terdekat daripada memotongnya. Lihat komentar saya pada jawaban Robby Pond untuk detail lebih lanjut.
MarredCheese
38

Melihat kebutuhan Anda, ada solusi alternatif juga. Tampaknya Anda tahu dimensi dalam dp pada waktu kompilasi, sehingga Anda dapat menambahkan entri dimen di sumber daya. Kemudian Anda dapat meminta entri dimen dan itu akan secara otomatis dikonversi ke piksel dalam panggilan ini:

final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);

Dan dimens.xml Anda akan memiliki:

<dimen name="dimen_entry_in_dp">72dp</dimen>

Memperluas ide ini, Anda cukup menyimpan nilai 1dp atau 1sp sebagai entri dimen dan kueri nilai dan menggunakannya sebagai pengganda. Dengan menggunakan pendekatan ini, Anda akan mengisolasi kode dari hal-hal matematika dan bergantung pada perpustakaan untuk melakukan perhitungan.

anggur
sumber
Perhatikan bahwa nilai kembali sebenarnya adalah int, sehingga akan dilemparkan ke float.
CorayThan
Ini adalah jawaban yang buruk karena itu adalah tarif menjadi dinamis
Johny19
37

Cara paling sederhana (dan bahkan bekerja dari api 1) yang diuji adalah:

getResources().getDimensionPixelSize(R.dimen.example_dimen);

Dari dokumentasi:

Ambil dimensi untuk ID sumber daya tertentu untuk digunakan sebagai ukuran dalam piksel mentah. Ini sama dengan getDimension (int), kecuali nilai yang dikembalikan dikonversi ke piksel integer untuk digunakan sebagai ukuran. Konversi ukuran melibatkan pembulatan nilai dasar, dan memastikan bahwa nilai dasar yang tidak nol setidaknya berukuran satu piksel.

Ya itu pembulatan nilainya tetapi tidak terlalu buruk (hanya dalam nilai aneh pada perangkat hdpi dan ldpi perlu menambahkan sedikit nilai ketika ldpi tidak terlalu umum) Saya menguji dalam perangkat xxhdpi yang mengubah 4dp menjadi 16 (piksel) dan itu adalah benar.

David
sumber