Как установить размер и макет в onSizeChanged? - PullRequest
26 голосов
/ 07 июня 2011

Я не могу заставить свои элементы, например ListView, правильно изменить размер.

Я получил ListActivity для поиска, с панелью инструментов, окном редактирования и списком.Идея состоит в том, чтобы скрыть панель действий во время отображения клавиатуры.

Я расширил LinearLayout, чтобы прослушать изменения размера представления (как рекомендовано здесь ):

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

    }
}

Скрытие / отображение панели действий работает, как и ожидалось, но есть пробел ниже ListView той же высоты, что и скрытая панель действий.Как только любое графическое изменение (например, запись в поле ввода), ListView заполняет пробел.Подобное поведение проявляется в обратном порядке при скрытии клавиатуры.

enter image description here

[Правка]

Та же проблема возникает и при изменении другой раскладки.Изменение Visibility вещей в onSizeChanged показывает непосредственно, но изменение размеров и полей не отображается, пока какое-либо другое действие пользователя не перерисовает эти представления.Invalidation не работает с onSizeChanged.

[/ Edit]

Я попытался обновить графику с помощью:

  • invalidate, так какпользовательский LinearLayout и ListView (как рекомендовано здесь )
  • notifyDataSetChanged на адаптере списка
  • forceLayout

... и более, без успеха.Почему ListView сначала не изменяется?Нужно ли переопределять onLayout в моем расширенном LinearLayout?Что я пропустил?

Ответы [ 4 ]

36 голосов
/ 21 июня 2011

Добавление следующего в конце onSizeChanged() решит это:

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

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

См. Ответ на этот вопрос: Представления внутри пользовательской группы ViewGroup не отображаются после изменения размера

0 голосов
/ 16 июня 2011

Вы можете принудительно перерисовать ListView, изменив его высоту на 1px и вызвав

requestLayout()

0 голосов
/ 18 июня 2011

Можно сделать то, что вы хотите, зарегистрировав setOnFocusChangeListener и setOnClickListener в EditText.

Существует множество различных сценариев, которые необходимо учитывать, когда речь идет о навигации, и, возможно, придется изменить некоторые вещи для работы с определенным макетом.

В любом случае, начните с переопределения onSizeChanged, чтобы показать скрытый элемент при касании кнопки назад.

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

В ListActivity мы берем MyLinearLayout и передаем ему this. Затем setOnFocusChangeListener регистрируется для обработки вещей, когда фокус EditText изменяется. SetOnClickListener используется, чтобы скрыть элемент, когда EditText уже имеет фокус.

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

        .....
    }

    .....
}

Я приведу рабочий пример позже, но сейчас мне пора.

0 голосов
/ 16 июня 2011

Это может быть длинный выстрел ...

Вы пытались играть с настройкой android:layout_height="" для ListView?

Возможно, с помощью match_parent или wrap_content могли бызаставить его работать ...

Как я уже сказал ... длинный выстрел!

...