2011-06-07 10 views
25

Nie mogę pobrać elementów, na przykład ListView, aby zmienić rozmiar poprawnie.Jak ustawić rozmiar i układ w onSizeChanged?

Mam do wyszukiwania ListActivity, z deską rozdzielczą, polem edycji i widokiem listy. Chodzi o to, aby ukryć pasek akcji podczas wyświetlania klawiatury.

ja przedłużony LinearLayout, aby słuchać, aby wyświetlić zmiany rozmiaru (jak zaleca 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); 

    } 
} 

Ukrywanie/pokazywanie z actionbar działa zgodnie z oczekiwaniami, ale istnieje luka poniżej ListView tej samej wysokości, co ukryty pasek akcji. Gdy tylko nastąpi zmiana grafiki (np. Wpisanie w polu edycji), ListView wypełnia lukę. Podobne zachowanie pojawia się w odwrotnej kolejności podczas ukrywania klawiatury.

enter image description here

[Edytuj]

Ten sam problem pojawia się również w innych zmieniając układ. Zmiana Visibility rzeczy w onSizeChanged pokazuje się bezpośrednio, ale zmiana rozmiarów i marginesów nie jest wyświetlana, dopóki inna akcja użytkownika nie przerysuje tych widoków. Unieważnienie nie działa od onSizeChanged.

[/ Edit]

Próbowałem odświeżyć grafikę według:

  • invalidate -ing zarówno zwyczaj LinearLayout i tym ListView (jak zaleca here)
  • notifyDataSetChanged na lista: adapter
  • forceLayout

... i więcej bez powodzenia. Dlaczego zmiana rozmiaru ListView nie jest na początku? Czy w rozszerzonym LinearLayout muszę zastąpić onLayout? Co przeoczyłem?

+0

Nie każdy aktualizacja działa, zauważyłem. "Jak tylko zmieni się grafika", napisałem. Ale na przykład wyskakujące okienko nie spowoduje wprowadzenia zmian. Myślę, że właściwe elementy muszą zostać unieważnione, ale nie. – JOG

+0

Problem pojawia się również przy wszystkich zmianach układu, na przykład przy zmianie marginesów EditText. Jednak elementy wstawiania elementów, na przykład przycisk po prawej stronie pudełka, są wyświetlane natychmiast. – JOG

Odpowiedz

32

Dodawanie następujące po zakończeniu onSizeChanged() będzie rozwiązać:

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

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

Patrz odpowiedź na to pytanie: Views inside a custom ViewGroup not rendering after a size change

+12

Widok ma metodę post(), więc nie trzeba przydzielać procedury obsługi. – ThomasW

+0

Zmieniłem rozmiar widoków podrzędnych w 'onSizeChanged', więc musiałem zmienić rozmiar tych widoków podrzędnych w działaniu przed wywołaniem' requestLayout() ' –

0

Może to być długi strzał ...

Czy próbowałeś grać z ustawieniem android:layout_height="" dla ListView?

Może użyciu match_parent lub wrap_content może zmusić go do pracy ...

Jak powiedziałem ... długi strzał!

+0

Podobnie jak sugestia @ PravinCG, to nie działa. Wygląda na to, że żadne zmiany układu wprowadzone w 'onSizeChanged' w dowolnym widoku nie są stosowane, dopóki nie zostanie wykonana kolejna aktualizacja układu. – JOG

0

Można wymusić ListView odświeżenia poprzez zmianę jego wysokości przez 1px i nazywając

requestLayout()

+0

Próbowaliśmy go, i to nie działa, niestety: ('setLayoutParams. Nowych LayoutParams (LayoutParams.FILL_PARENT, (int) getResources() getDimension (R.dimen.another_value)));' 'requestLayout ();' Otrzymuje nową wysokość tylko po zmianie dowolnego układu. Podobnie jak na moich zrzutach ekranu. To samo zachowanie pojawia się również we wszystkich widokach, które próbuję modyfikować w metodzie 'onSizeChanged'. – JOG

0

Jest możliwe, aby robić to, co chcesz, rejestrując setOnFocusChangeListener i setOnClickListener do EditText.

Istnieje wiele różnych scenariuszy do rozważenia, jeśli chodzi o nawigację i rzeczy mogą wymagać zmiany w celu pracy z określonym układem.

W każdym razie zacznij od przesłonięcia onSizeChanged, aby pokazać ukryty element po dotknięciu przycisku Wstecz.

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); 
    } 
} 

W ListActivity pobieramy MyLinearLayout i przekazać this do niego. Następnie rejestrowany jest setOnFocusChangeListener do obsługi rzeczy, gdy zmienia się ostrość EditText. Zestaw setOnClickListener służy do ukrycia elementu, gdy EditText już jest aktywny.

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); 
      } 
     }); 

     ..... 
    } 

    ..... 
} 

Podam przykład pracy później, ale muszę teraz działać.