Как я могу масштабировать размер шрифта на основе android displayMetrics?

Я пишу приложение, чтобы показать простые цифровые часы в Android, и мне нужно масштабировать размер шрифта TextView, чтобы он как можно больше заполнил экран. Я нашел довольно простой способ масштабирования размера текста с помощью displayMetrics, но на некоторых устройствах он работает некорректно. То, чего я хочу добиться, выглядит так: Как я могу масштабировать размер шрифта на основе android displayMetrics?

Я бы работал только в ландшафтном режиме, и я хотел бы, чтобы он работал на моих старых смартфонах и планшетах, лежащих без дела, а также на более новых устройствах. Так что у меня есть множество типов экранов, которые я могу удовлетворить.

Чтобы масштабировать шрифт, я делаю следующее

    ...
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_show_clock);

    // Get screen size and calculate text size needed to fit
    // TODO: doesn't work well on some devices
    TextView tvScreenSize = findViewById(R.id.tvScreenSize);
    DisplayMetrics displayMetrics = new DisplayMetrics(); // From: https://stackoverflow.com/questions/4743116/get-screen-width-and-height
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    // The screen height and width are recalculated automatically by Android when the screen is redrawn on a rotation
    height = displayMetrics.heightPixels;
    width = displayMetrics.widthPixels;
    textSP = width / 12; // Empirical value
    String hString = Integer.toString(height);
    String wString = Integer.toString(width);
    tvScreenSize.setText("h: " + hString + "  w:" + wString);

    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {

            // Display time of day
            Date curDate = new Date();
            TextView tvTime = findViewById(R.id.clockView);
            String timeStr = format.format(curDate);

            tvTime.setText(timeStr);
            tvTime.setScaleY(1.5f);
            tvTime.setWidth(width * 8 / 10); // Make it fill 80% of the screen
            tvTime.setHeight(height * 8 / 10);
            tvTime.setTextSize(textSP);
            ...

Сувенир с линией:

textSP = width / 12; // Empirical value

Для некоторых экранов хорошо работает значение 6. Для других экранов это создает настолько большой шрифт, что видна только небольшая его часть. Изменение этого значения на 12 помогает.

Кажется, я что-то упускаю, связанное с плотностью экрана, но что?

Спасибо!

КОНЕЧНЫЙ РЕЗУЛЬТАТ: Для тех, кто пытается масштабировать текст, как я, вот окончательный код после ввода от ismail:

Файл activity_main.xml:

?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout 
xmlns:android = "http://schemas.android.com/apk/res/android"
xmlns:app = "http://schemas.android.com/apk/res-auto"
xmlns:tools = "http://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity">

<TextView
    android:id = "@+id/tvClockFace"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content"
    android:layout_marginBottom = "6dp"
    android:text = "12:34"
    android:textColor = "@android:color/holo_red_dark"
    android:textSize = "30sp"
    android:textStyle = "bold"
    android:typeface = "monospace"
    app:fontFamily = "monospace"
    app:layout_constraintBottom_toBottomOf = "parent"
    app:layout_constraintLeft_toLeftOf = "parent"
    app:layout_constraintRight_toRightOf = "parent"
    app:layout_constraintTop_toTopOf = "parent" />

<TextView
    android:id = "@+id/tvScreenSize"
    android:layout_width = "wrap_content"
    android:layout_height = "wrap_content"
    android:layout_marginEnd = "8dp"
    android:layout_marginRight = "8dp"
    android:layout_marginBottom = "8dp"
    android:text = "H:... W:..."
    android:textSize = "14sp"
    app:layout_constraintBottom_toBottomOf = "parent"
    app:layout_constraintEnd_toEndOf = "parent" />

</android.support.constraint.ConstraintLayout>

И MainActivity.java:

package com.schalkx.testautosizeclockdisplay;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.Display;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Scale the textsize automatically
    Display display = getWindowManager().getDefaultDisplay();
    DisplayMetrics outMetrics = new DisplayMetrics ();
    display.getMetrics(outMetrics);

    float density  = getResources().getDisplayMetrics().density;
    float dpHeight = outMetrics.heightPixels / density;
    float dpWidth  = outMetrics.widthPixels / density;

    // Convert height and width to integer values
    float fTextSize = dpWidth/4; // Trial and error
    // int iTextSize = Math.round(fTextSize);
    int scrHeight = Math.round(dpHeight);
    int scrWidth = Math.round(dpWidth);

    // Display de height and width on screen (for reference)
    String wString = Integer.toString(scrWidth); // In case you need the width
    String hString = Integer.toString(scrHeight); // Same for height
    TextView tvScreenSize = findViewById(R.id.tvScreenSize);
    tvScreenSize.setText("h: " + hString + "  w:" + wString);

    // Scale the font of the clock face
    TextView tvClockFace = findViewById(R.id.tvClockFace);
    // tvClockFace.setHeight(50);
    // tvClockFace.setWidth(100);
    tvClockFace.setTextSize(fTextSize);
    tvClockFace.setScaleY(1.5f);
    }
}

используйте github.com/intuit/ssp для масштабирования размера шрифта в соответствии с показателями отображения.

Krishna sheladiya 28.05.2019 05:29
1
1
788
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вообще не используйте значение пикселя в своем коде. конвертировать пиксель в независимый от устройства пиксель (dp)

public static float convertPixelsToDp(float px, Context context){
    return px / ((float) context.getResources().getDisplayMetrics().densityDpi/ 
         DisplayMetrics.DENSITY_DEFAULT);
}
Ответ принят как подходящий

Для лучшего отображения вы должны работать с dp вместо px, вот как получить размер dp:

Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);

float density  = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth  = outMetrics.widthPixels / density;

так что теперь вы можете установить размер текста в соответствии с размером экрана dpHeight и dpWidht

Другие вопросы по теме