如何根据应用程序小部件中文本视图中的小部件大小调整文本大小?
Posted
技术标签:
【中文标题】如何根据应用程序小部件中文本视图中的小部件大小调整文本大小?【英文标题】:How to resize text size depending on widget size in a textview in an appwidget? 【发布时间】:2012-08-27 12:46:59 【问题描述】:我已经为 android 编程了一段时间,但这真的让我很困惑。
所以我有一个带有 textview 的简单 appwidget。如果用户调整小部件的大小,我只是希望该文本视图内的文本字体大小按比例放大/缩小,以便在调整应用程序大小时使文本更大。我尝试了几种解决方案,但都失败了:
仅使用“sp”(缩放像素)单位作为字体大小 - 当小部件大小发生变化时,这不会缩放文本(我也没想到!)。
李>用我自己的和覆盖的 onSizeChanged 方法扩展 TextView。但是您不能在小部件中包含基本 UI 类的后代(文档也说明了这一点)。
由于没有任何方法可以获取当前的 appWidget 大小,所以我只是卡在这里。
是的,我知道一种解决方案是创建不同版本的小部件,例如 1x4 和 2x4 等,但肯定还有另一种方法吗?
欢迎提出任何想法?
【问题讨论】:
作为对后来读者的附注,我可以说可以从 API 16+ 开始。您可以在小部件中覆盖一个回调方法: onAppWidgetOptionsChanged ,您可以从该方法获得最大宽度和高度(如下文所述)。但在 API 16 以下,调整大小并不容易。 【参考方案1】:无法根据父级大小自动缩放 TextView 的文本。一种解决方法是覆盖 TextView 的 onDraw
方法并手动实现缩放。
至于 appwidget:您无法检索可调整大小的 appwidget 的当前大小,因为它们旨在与 ListView
和 GridView
容器一起使用。这些容器将自动管理内容的缩放和间距,并且如果内容不适合 appwidget 的当前大小,它们会使其自身可滚动。
如果您不使用ListView
或GridView
,在我看来,“缩放”应用小部件组件的最佳方法是您已经提到的方法:使用不同的不可调整大小的应用小部件。
【讨论】:
就像我说的,扩展 TextView 和覆盖 onDraw 的解决方法不适用于 appwidgets,因为文档还指出。也许我可以将 TextView 放在 GridView 中,它会起作用吗? 一行一列的“GridView”,TextView 设置为 fill_parent 可以工作。如果不是,您可能应该求助于不同大小的不可调整大小的 appwidgets。 我无法让 gridview 的方法也能正常工作。我想唯一的方法是拥有几个具有不同不可调整大小的 appwidgets(这似乎是其他人也这样做的方法)。好吧,希望至少其他人可以从我的问题中受益并节省时间!【参考方案2】:您可以调用AppWidgetManager.getAppWidgetOptions(OPTION_APPWIDGET_MAX_WIDTH) 来获取最大宽度(与小部件高度相同的方式)并相应地调整文本大小。限制:此方法适用于 API 级别 16
【讨论】:
这没问题,虽然不同的启动器会传递稍微不同的值(dp 与 px)等,所以正确设置有点混乱。【参考方案3】:这是原始的方式,但它有效:
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();
【讨论】:
【参考方案4】:结合上面的答案和来自https://***.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;
【讨论】:
以上是关于如何根据应用程序小部件中文本视图中的小部件大小调整文本大小?的主要内容,如果未能解决你的问题,请参考以下文章
将 headerView 添加到小部件上的小部件中的 listView 调整大小 android