2011-06-07 13 views
25

No puedo obtener mis elementos, por ejemplo ListView, para cambiar el tamaño correctamente.¿Cómo establecer el tamaño y el diseño en onSizeChanged?

Obtuve un ListActivity para buscar, con un tablero de instrumentos, un cuadro de edición y una vista de lista. La idea es ocultar la barra de acciones mientras se muestra el teclado.

extendí LinearLayout, a escuchar para ver los cambios de tamaño (como se recomienda here):

public class SizeChangingLinearLayout extends LinearLayout { 
    //... 
    @Override 
    protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) 
    {   
     View actionbar = mainView.findViewById(R.id.actionbar); 

     if (yNew > yOld) 
      actionbar.setVisibility(View.VISIBLE); 
     else if (yNew < yOld) 
      actionbar.setVisibility(View.GONE); 

     super.onSizeChanged(xNew, yNew, xOld, yOld); 

    } 
} 

El escondite/proyección de la barra de acción funciona como se esperaba, pero hay un hueco por debajo de la ListView de la misma altura que la barra de acciones oculta Tan pronto como los gráficos cambian (por ejemplo, escribiendo en la caja de edición), el ListView llena el espacio. Un comportamiento similar aparece al revés, cuando se oculta el teclado.

enter image description here

[Editar]

El mismo problema aparece también en el cambio de diseño de otros. El cambio de Visibility de cosas en onSizeChanged muestra directamente, pero cambiar los tamaños y los márgenes no se muestra hasta que otra acción del usuario redibuja esas vistas. La invalidación no funciona desde onSizeChanged.

[/ editar]

he tratado de actualizar los gráficos por:

  • invalidate -ing tanto la costumbre LinearLayout y la ListView (como recomendada here)
  • notifyDataSetChanged en el del adaptador de la lista
  • forceLayout

... y más, sin éxito. ¿Por qué el ListView no cambia de tamaño al principio? ¿Tengo que anular onLayout en mi LinearLayout extendido? ¿Qué me he perdido?

+0

No cualquier actualización funciona, lo he notado. "Tan pronto como los gráficos cambian", escribí. Pero, por ejemplo, una ventana emergente no hará que se muestren los cambios realizados. Supongo que los elementos correctos deben ser invalidados, pero no es así. – JOG

+0

El problema también aparece para todos los cambios de diseño, por ejemplo, para cambiar los márgenes de EditText. Pero _agregar_ elementos de diseño, por ejemplo un botón a la derecha del cuadro, se muestra inmediatamente. – JOG

Respuesta

32

Agregar el siguiente código al final de onSizeChanged() lo resolverá:

Handler handler = new Handler(); 
handler.post(new Runnable() { 

    @Override 
    public void run() { 
     requestLayout(); 
    } 
}); 

Ver la respuesta a esta pregunta: Views inside a custom ViewGroup not rendering after a size change

+12

La vista tiene un método post(), por lo que no necesita asignar el controlador. – ThomasW

+0

Estaba cambiando el tamaño de las vistas secundarias en 'onSizeChanged', así que tuve que poner el cambio de tamaño de dichas vistas secundarias en el ejecutable antes de llamar a' requestLayout() ' –

0

Esto podría ser una posibilidad remota ...

Ha intentado jugar con la configuración android:layout_height="" para la ListView?

Tal vez usando match_parentwrap_content o podría obligarlo a trabajar ...

Como ya he dicho ... una posibilidad muy remota!

+0

Al igual que la sugerencia de @ PravinCG, no funciona. Aparentemente, no se aplica ningún cambio de diseño realizado en 'onSizeChanged' en ninguna vista hasta que se realice otra actualización de diseño. – JOG

0

puede forzar la ListView para volver a trazar cambiando su altura por 1 píxel y llamando

requestLayout()

+0

probado, y no funciona, por desgracia: 'setLayoutParams (. LayoutParams nuevas (LayoutParams.FILL_PARENT, (int) getResources() getDimension (R.dimen.another_value)));' ' requestLayout();' Obtiene la nueva altura solo después de que cambie cualquier otro diseño. Al igual que en las capturas de pantalla mías. El mismo comportamiento también aparece en todas las vistas que trato de manipular en el método 'onSizeChanged'. – JOG

0

Es posible hacer lo que desee registrar un setOnFocusChangeListener y una setOnClickListener a la EditText.

Hay muchos escenarios diferentes a considerar en lo que respecta a la navegación y es posible que haya que cambiar las cosas para que funcionen con un diseño determinado.

De todos modos, comience anulando onSizeChanged para mostrar el elemento oculto cuando se toca el botón Atrás.

public class MyLinearLayout extends LinearLayout { 

    private MyListActivity mMyListActivity; 

    public MyLinearLayout(Context context) { 
     super(context); 
    } 

    public MyLinearLayout(Context context, AttributeSet attrs) { 
     super(context, attrs);  
    } 

    public void setMyListActivity(MyListActivity mla) { 
     mMyListActivity = mla; 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     // show the element when we get more room  
     if (h > oldh) { 
      if (mMyListActivity != null) { 
       mMyListActivity.showBar(); 
      } 
     } 
     super.onSizeChanged(w, h, oldw, oldh); 
    } 
} 

En el ListActivity que agarrar la MyLinearLayout y pasan this a ella. Luego, se establece un setOnFocusChangeListener para manejar cosas cuando el foco de EditText cambia. El setOnClickListener se usa para ocultar el elemento cuando EditText ya tiene foco.

public class MyListActivity extends ListActivity { 

    private ArrayList<MyData> mDataList = new ArrayList<MyData>(); 

    private MyLinearLayout mMyLinearLayout; 
    private LinearLayout mHideMeLinearLayout; 
    private EditText mEditText; 

    public void showBar() { 
     if (mHideMeLinearLayout != null) { 
      mHideMeLinearLayout.setVisibility(View.VISIBLE); 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Get MyLinearLayout and pass this to it. 
     mMyLinearLayout = (MyLinearLayout) findViewById(R.id.myLinearLayout); 
     mMyLinearLayout.setMyListActivity(this); 

     // the LinearLayout to be hidden 
     mHideMeLinearLayout = (LinearLayout) findViewById(R.id.LinearLayoutToHide); 

     mEditText = (EditText) findViewById(R.id.editText);  
     mEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 
      @Override 
      public void onFocusChange(View v, boolean hasFocus) { 
       InputMethodManager imm = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE); 
       if (hasFocus) { 
        imm.showSoftInput(mEditText, 0); 
        mHideMeLinearLayout.setVisibility(View.GONE); 
       } else { 
        imm.hideSoftInputFromWindow(mMyLinearLayout.getWindowToken(), 0); 
        mHideMeLinearLayout.setVisibility(View.VISIBLE); 
       } 
      } 
     }); 
     mEditText.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       mHideMeLinearLayout.setVisibility(View.GONE); 
      } 
     }); 

     ..... 
    } 

    ..... 
} 

Proporcionaré un ejemplo de trabajo más adelante, pero tengo que ejecutar ahora.

Cuestiones relacionadas