2012-09-02 17 views
6

He programado Android por un tiempo, pero esto realmente me desconcierta.¿Cómo cambiar el tamaño del texto según el tamaño del widget en una vista de texto en un appwidget?

Tengo un appwidget simple con una vista de texto. Simplemente quiero que el tamaño de fuente del texto dentro de esa vista de texto aumente o disminuya si el usuario cambia el tamaño del widget para aumentar el tamaño del texto si se cambia el tamaño de la aplicación. He intentado varias soluciones, pero todo falla:

  1. simple uso de la unidad de "SP" (píxeles escalados) para el tamaño de la fuente - esto no escala el texto cuando cambia el tamaño Widget (no me esperaba demasiado como ¡bien!).

  2. Extendiendo TextView con mi propio método y el método onSizeChanged. Pero no puede tener descendientes de clases de IU básicas en un widget (la documentación también lo indica).

Dado que no hay métodos para obtener el tamaño actual del appWidget, simplemente estoy atascado aquí.

Sí, sé que una solución es crear diferentes versiones del widget como 1x4 y 2x4, etc., pero seguramente hay otra manera?

¿Alguna idea es bienvenida?

+0

Como nota adicional para lectores posteriores, puedo decir que es posible hacerlo desde API 16+. Hay un método de devolución de llamada que puede anular en su widget: onAppWidgetOptionsChanged y de este método puede obtener el ancho y el alto máximos (como se señala a continuación). Pero debajo de API 16 no es realmente fácil hacer el cambio de tamaño. – zaifrun

Respuesta

3

No es posible escalar automáticamente el texto de una Vista de texto en función del tamaño principal. Una solución alternativa sería anular el método onDraw de TextView e implementar la escala manualmente.

En cuanto a los appwidgets: No se puede recuperar el tamaño actual de un appwidget redimensionable porque están destinados para su uso con los contenedores ListView y GridView. Estos contenedores administrarán la ampliación y el espaciado del contenido de forma automática y se harán desplazables si el contenido no cabe en el tamaño actual del appwidget.

Si no está utilizando un ListView o una GridView me parece la mejor manera de "escala" los componentes de un appwidget es el método que ya se ha mencionado: Usar diferentes appwidgets no de tamaño variable.

+0

Como dije, la solución con la extensión de TextView y la anulación de onDraw no funciona para appwidgets, como también indica la documentación. ¿Tal vez podría poner el TextView dentro de un GridView y funcionaría? – zaifrun

+0

Podría funcionar un 'GridView' con una fila y una columna con la opción TextView configurada en fill_parent.Si no es así, probablemente debas recurrir a appwidgets de tamaño diferente y no redimensionables. –

+0

No pude conseguir el enfoque con gridview para trabajar también. Supongo que la única forma es tener varios appwidgets con diferentes tamaños que no se puedan redimensionar (esto parece ser un acercamiento para que otros también lo hagan). ¡Bien, espero que al menos otros se puedan beneficiar de mi pregunta y ahorren tiempo! – zaifrun

3

Puede llamar al AppWidgetManager.getAppWidgetOptions(OPTION_APPWIDGET_MAX_WIDTH) para obtener el ancho máximo (del mismo modo que la altura del widget) y ajustar el tamaño del texto en consecuencia. Limitación: este método está disponible desde el nivel API 16

+1

Esto funciona bien, aunque diferentes lanzadores pasarán valores ligeramente diferentes (dp vs. px), etc. por lo que hacer las cosas bien es algo desordenado. –

1

Esta es la forma primitiva pero funciona:

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(); 
1

La combinación de las respuestas anteriores y un tijeretazo-IT código preciosa desde https://stackoverflow.com/a/7875656/6364860, lo tengo trabajando como esto:

* Tenga en cuenta que tenía un botón circular con texto, por lo que solo necesitaba la dimensión más pequeña.

@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; 
} 
Cuestiones relacionadas