TextView.setTextSize berperilaku tidak normal - Cara menyetel ukuran teks textview secara dinamis untuk layar yang berbeda

119

Panggilan TextView.setTextSize()bekerja secara tidak normal. Tepat setelah panggilan ke setTextSizejika kita mendapatkan getTextSizekembali nilai yang jauh lebih tinggi dari apa yang kita atur sebelumnya.

Inilah yang kami lakukan:

zoomControl.setOnZoomInClickListener(new OnClickListener() {
    public void onClick(View view) {
        float size = mViewShabad.getTextSize() + 1;
        textView.setTextSize(size);
    }
});

Adakah yang pernah melihat ini sebelumnya?

singhspk
sumber
2
Anda mendapatkan dan menyetel ukuran teks pada dua objek berbeda?
Cheryl Simon

Jawaban:

359

Perbedaannya di sini adalah bahwa dalam setTextSize(int size)metode, tipe unit secara default adalah "sp" atau "piksel berskala". Nilai ini akan menjadi dimensi piksel yang berbeda untuk setiap kepadatan layar (ldpi, mdpi, hdpi).

getTextSize(), di sisi lain, mengembalikan dimensi piksel teks yang sebenarnya.

Anda dapat menggunakan setTextSize(int unit, float size)untuk menentukan tipe unit. Nilai konstan untuk ini dapat ditemukan di kelas TypedValue, tetapi beberapa di antaranya adalah:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels
Kevin Coppock
sumber
Saya baru menemukannya dan akan mempostingnya di sini. Terima kasih banyak!
singhspk
1
Saya pikir itu sebenarnya harus oleh TypedValue (tunggal). Impornya adalah android.util.TypedValue;
Hein du Plessis
5
Juga untuk dicatat, itu hanya mulai melakukan ini di API level 7. "Gotcha" lain dalam API konyol.
mxcl
3
Penting untuk diperhatikan untuk urutan argumen - Saya tidak sengaja memiliki setTextSize (size, TypedValue.COMPLEX_UNIT_SP) karena itu adalah urutan yang salah duga!
Tandai
1
Menariknya, pada ICS di Galaxy Nexus saya, menggunakan setTextSize (14, TypedValue.COMPLEX_UNIT_SP) tidak berpengaruh (jadi menggunakan ukuran default), tetapi ketika saya meningkatkan ke Jelly Bean, tidak ada teks yang ditampilkan (seperti ukuran 0). Saya baru saja akan melaporkan bug Jelly Bean ketika saya menyadari kesalahan saya!
Tandai
20

masalah ini terjadi karena getTextSize()metode mengembalikan ukuran dalam piksel tergantung pada kepadatan layar! untuk mendapatkan TextSize Aktual gunakan ini:

DisplayMetrics metrics;
metrics = getApplicationContext().getResources().getDisplayMetrics();
float Textsize =myTextView.getTextSize()/metrics.density;
myTextView.setTextSize(Textsize+1);

saya harap ini menyelesaikannya :)

M_AWADI
sumber
2
Saya memecahkan masalah saya dengan menggunakan metrik tampilan dengan setTextSize(int unit, float size)
Edward Chiang
8

jika Pengaturan mengubah ukuran font , sesuatu penyebab kesalahan pertunjukan , Anda dapat melakukan sebagai :

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);
hui 谁 与 争辉
sumber
3
Siapa yang menyetel textSize DIP?
IgorGanapolsky
4

Ketika kita mencoba untuk masalah setText () secara terprogram dengan getTextSize (), mengembalikan nilai dalam px bukan sp / dp / dip dan kita tahu 1sp / dp = 1.5px (ukuran layar = 240).

 titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*1.5f)); 

berfungsi dengan sempurna untuk saya atau kita dapat menggunakan rasio displaymatrix ke px: sp / dp lalu ganti nilainya dengan 1.5f

means-> titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*your_sp_and_px_ratio_in_int f));
ranjan
sumber
3

Setelah sekian lama melanda hal ini dan akhirnya terselesaikan seperti ini

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
          getResources().getDimension(R.dimen.textsize));

buat folder dimen seperti ini res / values ​​/ dimensional.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <dimen name="textsize">8sp</dimen>

 </resources>
NagarjunaReddy
sumber
2

Singkatnya, jika Anda ingin memperkecil ukuran teks Anda

float size = mViewShabad.getTextSize()*1.1f;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

Karena getTextSize () mengembalikan UNIT_PX, maka kita harus menggunakan UNIT_PX

Frank Nguyen
sumber
1

Solusi Kotlin

Untuk menyetel menggunakan sumber daya, cukup gunakan ini:

textView.setTextSize(COMPLEX_UNIT_PX, textView.resources.getDimension(R.dimen.my_text_size))

Untuk melakukan hal yang sama dengan nilai resource, tambahkan properti ekstensi ini agar lebih mudah menyetel ukuran teks Anda

textView.textSizeRes = R.dimen.my_text_size

var TextView.textSizeRes
    get() = textSize.toInt()
    set(@DimenRes textSizeRes) {
        setTextSize(COMPLEX_UNIT_PX, resources.getDimension(textSizeRes))
    }
Gibolt
sumber
0

Menambahkan beberapa rasa ekstra untuk jawaban ini, karena juga menimbulkan sedikit kebingungan. Anda harus dapat melepaskan tes ini ke dalam @RunWith(AndroidJUnit4.class)tes apa pun yang Anda miliki di proyek Anda (Anda juga harus menambahkan dimens ke dimens.xml Anda).

Catatan: Semua tes ini lulus

@Test public void testScaledFontSizes() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    final Context context = InstrumentationRegistry.getTargetContext();

    Configuration configuration = context.getResources().getConfiguration();
    configuration.fontScale = 2.0f;
    configuration.densityDpi = 160; // mdpi, 1:1
    context.getResources().updateConfiguration(configuration, null);

    float scaledTextSize = context.getResources().getDimensionPixelSize(R.dimen.sp_15);
    assertEquals(30.0f, scaledTextSize);

    // Create a new TextView with the explicitly set configuration
    TextView textView = new TextView(context);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, scaledTextSize);

    // 30, because font size is scaled
    assertEquals(30.0f, textView.getTextSize());

    // This is what we *don't* want, it's scaled *twice*!
    textView.setTextSize(scaledTextSize);
    assertEquals(60.0f, textView.getTextSize());

    // DP instead of SP tests
    float fifteenDp = context.getResources().getDimensionPixelSize(R.dimen.dp_15);
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fifteenDp);
    // Still 15, because it's DP, not SP
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(fifteenDp);
    // 30, because setTextSize DOES font scaling
    assertEquals(30.0f, textView.getTextSize());
  }
}

Hal besar yang saya temukan adalah yang TextView.setTextSize(float) menerapkan penskalaan font , jadi jika Anda mengirimkan dimen yang sudah diberi label sebagai SP, bukan DP, maka itu akan menerima penskalaan font dua kali .

Kevin Grant
sumber