Как изменить размер текста в зависимости от размера виджета в текстовом виде в приложении?

Я запрограммировал Android некоторое время, но это меня озадачивает.

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

  1. Просто используя блок «sp» (масштабированный пиксель) для размера шрифта – это не масштабирует текст при изменении размера виджета (я тоже этого не ожидал!).

  2. Расширение TextView с моим собственным и переопределяющим методом onSizeChanged. Но вы не можете иметь потомков базовых классов пользовательского интерфейса в виджетах (в документации также указано это).

Поскольку нет способов даже получить текущий размер appWidget, я просто застрял здесь.

Да, я знаю, что одним из решений является создание разных версий виджета, таких как 1×4 и 2×4 и т. Д., Но, конечно, есть другой способ?

Любые идеи приветствуются?

Невозможно автоматически масштабировать текст TextView на основе размера родителя. onDraw было бы переопределить метод onDraw TextView и реализовать масштабирование вручную.

Что касается appwidgets: вы не можете получить текущий размер изменяемого размера Appwidget, потому что они предназначены для использования с контейнерами ListView и GridView . Эти контейнеры будут управлять масштабированием и интервалом содержимого автоматически и будут прокручиваться, если содержимое не может соответствовать текущему размеру appwidget.

Если вы не используете ListView или GridView мне кажется, что лучший способ «масштабировать» компоненты appwidget – это метод, о котором вы уже упоминали: используйте разные неперемасштабируемые appwidgets.

Вы можете вызвать AppWidgetManager.getAppWidgetOptions (OPTION_APPWIDGET_MAX_WIDTH), чтобы получить максимальную ширину (точно так же, как высота виджета) и соответственно изменить размер текста. Ограничение: этот метод доступен с уровня API 16

Это примитивный способ, но он работает:

 AppWidgetManager manager = AppWidgetManager.getInstance(this); ComponentName thisWidget = new ComponentName(this, AppWidget.class); int[] widgetId = manager.getAppWidgetIds(thisWidget); Bundle options; options = manager.getAppWidgetOptions(widgetIds[1]); int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); int maxWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH); int minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); int maxHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT); int maxtextLen = (maxWidth / currentTextSize) * (maxHeight / currentTextSize); Boolean isFit = maxtextLen > textInWidgetTextView.length(); 

Объединив ответы выше и прекрасный снимок кода – от https://stackoverflow.com/a/7875656/6364860 , я начал работать так:

* Примечание. У меня была круглая кнопка с текстом, поэтому мне нужно было только самое маленькое измерение.

 @Override public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions){ super.onAppWidgetOptionsChanged(context,appWidgetManager,appWidgetId,newOptions); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { int maxWidth = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH); int maxHeight = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT); int size = Math.min(maxHeight,maxWidth); int pxSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,size,context.getResources().getDisplayMetrics()); RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_button); float newSize = refitText(context.getString(R.string.button_text),pxSize); remoteViews.setTextViewTextSize(R.id.widget_text, TypedValue.COMPLEX_UNIT_PX,newSize); appWidgetManager.updateAppWidget(appWidgetId,remoteViews); } } private float refitText(String text, int textWidth) { if (textWidth <= 0) return 0; float hi = 100; float lo = 2; final float threshold = 0.5f; // How close we have to be Paint testPaint = new Paint(); while((hi - lo) > threshold) { float size = (hi+lo)/2; testPaint.setTextSize(size); if(testPaint.measureText(text) >= textWidth) hi = size; // too big else lo = size; // too small } // Use lo so that we undershoot rather than overshoot return lo; }