Сохранение последнего видимого элемента ListView при изменении размера ListView
Я хочу просто, ну, по крайней мере, я думал, что это будет просто.
Я просто хочу окно, где EditText находится в нижней части экрана, а остальная часть пространства заполняется ListView.
К сожалению, это не сработало, как я ожидал. Я хочу следующее изображение. Есть ли простой способ сделать это в XML, или я должен написать для этого специальный код?
![What I want]()
Мой проблемный исходный код Android.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/demolist"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
>
</ListView>
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0">
</EditText>
</LinearLayout >
Ответы
Ответ 1
Что вы хотите
Последний видимый элемент без клавиатуры
![Last Visible Item Without Keyboard]()
Последний видимый элемент с клавиатурой
![Last Visible Item With Keyboard]()
Последний видимый элемент с большим входом
![Last Visible Item With larger input]()
Вот как я это сделал.
Резюме
- Установите android: stackFromBottom = "true" и android: transcriptMode = "alwaysScroll" в вашем представлении списка
- Установить android: windowSoftInputMode = "adjustPan" в действии
- Вызов adapter.notifyDataSetChanged();, когда вы добавляете новые чаты, чтобы вид списка всегда прокручивался до последней позиции.
- Установите android: inputType = "textMultiLine" и android: maxLines = "4" в EditText для расширения текстового поля
Подробнее
активность
<activity android:name="MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan"></activity>
Просмотр чата
<RelativeLayout
android:id="@+id/chat_header"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:padding="3dp" >
<Button
android:id="@+id/btnBackChat"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentLeft="true"
android:background="@drawable/back_button" />
<TextView
android:id="@+id/txt_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/btnBackChat"
android:layout_centerHorizontal="true"
android:textColor="@android:color/white"
android:textSize="18sp" />
<ImageView
android:id="@+id/imgViewProfileChat"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/form"
android:layout_below="@+id/chat_header"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"/>
<RelativeLayout
android:id="@+id/form"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="vertical" >
<ImageButton
android:id="@+id/btnAttach"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:contentDescription="@string/attach"
android:src="@drawable/attach_icon" />
<EditText
android:id="@+id/txtChat"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/btnSend"
android:layout_toRightOf="@+id/btnAttach"
android:inputType="textMultiLine"
android:maxLines="4" />
<Button
android:id="@+id/btnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="@string/send" />
</RelativeLayout>
Ответ 2
Я думаю, вы можете использовать AdapterView.getLastVisiblePosition() перед отображением клавиатуры.
Два решения здесь:
- в EditText нажмите
- благодаря функции OnScrollListener (и ее функции onScroll), которая прослушивает ваш ListView
затем используйте AdapterView.setSelection, чтобы перейти к этому элементу (или индексу - 2 или индексу - 3) после фокусировки EditText.
Ответ 3
Вы можете использовать android:windowSoftInputMode="adjustPan"
в вашем AndroidManifest.xml, как показано ниже
<activity android:name="com.example.SimpleListView"
android:label="@string/app_name"
android:windowSoftInputMode="adjustPan" >
Это даст результат, который вы хотите. Официальная документация по Android.
При желании вы можете указать режим транскрипции (если вы работаете над какой-либо функцией чата) для своего списка, если вы хотите автоматически прокручивать до конца списка. Вы также можете проверить android:transcriptMode="normal"
и посмотреть, подходит ли это.
Связанный ответ SO > . Официальный android doc.
<ListView
android:id="@+id/comments"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="alwaysScroll">
Это должно решить большинство ваших проблем, возможно, за исключением последнего (на изображении), который я не тестировал.
Ответ 4
Просто переопределите метод ListView # onSizeChanged (int w, int h, int oldw, int oldh), как показано ниже:
PS: Ваша высота ListView не может быть 0 в любое время, если она может 0, не работает.
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (getChildCount() == 0) {
return;
}
final int lastVisiblePosition = getLastVisiblePosition();
int firstVisiblePosition = getFirstVisiblePosition();
View last = getChildAt(lastVisiblePosition - firstVisiblePosition);
int top = last.getTop();
final int newTop = top + (h - oldh);
Log.d(getClass().getSimpleName(), "onSizeChanged(" + w + ", " + h + ", " + oldw + ", " + oldh + ")");
if (mFocusSelector == null) {
mFocusSelector = new FocusSelector();
}
post(mFocusSelector.setup(lastVisiblePosition, newTop));
super.onSizeChanged(w, h, oldw, oldh);
}
private class FocusSelector implements Runnable {
private int mPosition;
private int mPositionTop;
public FocusSelector setup(int position, int top) {
mPosition = position;
mPositionTop = top;
return this;
}
public void run() {
setSelectionFromTop(mPosition, mPositionTop);
}
}
Ответ 5
Я действительно получил то же поведение, которое вам нужно, добавив в объявление Activity
в манифесте android:windowSoftInputMode="adjustResize"
и в объявление ListView
android:transcriptMode="normal"
. Для изменения клавиатуры и ориентации.
Ответ 6
Мне тоже нужна эта функциональность. Здесь моя попытка, но она не совсем работает. Прокрутка немного беспорядочна (не всегда заканчивается там, где она должна), и это мешает сохранению положения прокрутки при вращении экрана.
@Override
public void onResume() {
super.onResume();
getListView().addOnLayoutChangeListener(stickyLastItemHandler);
}
@Override
public void onPause() {
super.onPause();
getListView().removeOnLayoutChangeListener(stickyLastItemHandler);
}
View.OnLayoutChangeListener stickyLastItemHandler = new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v,
int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
final int heightChange = (bottom - top) - (oldBottom - oldTop);
if (heightChange != 0) {
((AbsListView)v).smoothScrollBy(-heightChange, 1000);
}
}
};
Ответ 7
Вы можете сделать это через xml:
<ListView
android:stackFromBottom="true"
android:layout_height=0dp
android:layout_weight=1 />
Укладка вниз приведет к тому, что ListView будет прокручиваться по умолчанию,
установка веса ListView заполнит все возможное пространство внутри родительского вертикального LinearLayout.
Ответ 8
Я создал механизм компоновки для Android, который позволяет слушать скрытые и видимые изменения клавиатуры (среди многих других основных функций). Эта библиотека доступна по адресу http://phil-brown.github.io/AbLE/.
Просто добавьте jar
в каталог libs
(создайте эту папку, если она не существует), а вместо наследования с Activity
наследуйте от AbLEActivity
. Затем переопределите методы onKeyboardShown
и onKeyboardHidden
, и в них вы можете анимировать представление своего контента вверх или вниз по мере необходимости:
@Override
public void onKeyboardShown() {
//animate up
}
@Override
public void onKeyboardHidden() {
//animate down
}
Ответ 9
просто проверьте это: надеюсь, это поможет вам....
Предположим, что вы знаете, когда данные списка изменились, вы можете вручную указать списку для прокрутки вниз, установив список в последнюю строку. Что-то вроде этого:
private void scrollMyListViewToBottom() {
myListView.post(new Runnable() {
@Override
public void run() {
// Select the last row so it will scroll into view...
myListView.setSelection(myListAdapter.getCount() - 1) ;
}
});
}
или вы также можете попробовать это.. это работает для меня:
ChatAdapter adapter = new ChatAdapter(this);
ListView lview = (ListView) findViewById(R.id.chatList);
lview .setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
lview .setAdapter(adapter);
adapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
lv.setSelection(adapter.getCount() - 1);
}
});
Ответ 10
Follow these steps
--------------------
1. Update your activity in AndroidManifest.xml file like below
<activity
android:name=".MyListActivity"
android:windowSoftInputMode="adjustResize" />
2. Set your list view with like below.
mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
mListView.setStackFromBottom(true);
Я надеюсь, что это решит вашу проблему.
Ответ 11
В вашем ListAdapter вы можете сделать что-то вроде этого:
public View getView(int position, View convertView, ViewGroup parent) {
//buttonMore
if( position >= super.getCount() )
return textField ;
....
Таким образом, вы всегда получите свой последний элемент в списке в качестве текстового поля.
Ответ 12
Вам нужно установить позицию выбора... Но - странным образом, я действительно не понимаю, почему - вам нужно сделать это с помощью post()
public void ScrollToLast() {
yourList.clearFocus();
yourList.post(new Runnable() {
@Override
public void run() {
yourList.setSelection(items.size() - 1);
}
});
}
Итак, вы можете добавить TextWatcher для своего editText, и вы можете вызвать этот метод там... Таким образом, ваш список будет прокручиваться донизу.