ฉันมีความยาวListView
ที่ผู้ใช้สามารถเลื่อนไปมาก่อนที่จะกลับไปที่หน้าจอก่อนหน้า เมื่อผู้ใช้เปิดListView
อีกครั้งฉันต้องการให้รายการเลื่อนไปยังจุดเดียวกับที่เคยเป็นก่อนหน้านี้ ความคิดใด ๆ เกี่ยวกับวิธีการบรรลุสิ่งนี้?
ฉันมีความยาวListView
ที่ผู้ใช้สามารถเลื่อนไปมาก่อนที่จะกลับไปที่หน้าจอก่อนหน้า เมื่อผู้ใช้เปิดListView
อีกครั้งฉันต้องการให้รายการเลื่อนไปยังจุดเดียวกับที่เคยเป็นก่อนหน้านี้ ความคิดใด ๆ เกี่ยวกับวิธีการบรรลุสิ่งนี้?
คำตอบ:
ลองสิ่งนี้:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
// ...
// restore index and position
mList.setSelectionFromTop(index, top);
คำอธิบาย:
ListView.getFirstVisiblePosition()
ส่งคืนรายการที่มองเห็นได้ด้านบน แต่รายการนี้อาจถูกเลื่อนบางส่วนออกจากมุมมองและถ้าคุณต้องการคืนค่าตำแหน่งการเลื่อนที่แน่นอนของรายการคุณจะต้องได้รับการชดเชยนี้ ดังนั้นListView.getChildAt(0)
จะส่งกลับView
สำหรับรายการด้านบนแล้วส่งกลับญาติชดเชยจากด้านบนของView.getTop() - mList.getPaddingTop()
ListView
จากนั้นจะเรียกคืนListView
's เลื่อนตำแหน่งที่เราเรียกว่ามีค่าดัชนีของรายการที่เราต้องการและชดเชยการวางตำแหน่งขอบด้านบนจากด้านบนของที่ListView.setSelectionFromTop()
ListView
int index = mList.getFirstVisiblePosition();
mList.setSelectionFromTop(index, 0);
คำตอบที่ดี (+1)! ฉันได้รับการมองหาทางออกที่สง่างามสำหรับปัญหานี้
Parcelable state;
@Override
public void onPause() {
// Save ListView state @ onPause
Log.d(TAG, "saving listview state");
state = listView.onSaveInstanceState();
super.onPause();
}
...
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Set new items
listView.setAdapter(adapter);
...
// Restore previous state (including selected item index and scroll position)
if(state != null) {
Log.d(TAG, "trying to restore listview state");
listView.onRestoreInstanceState(state);
}
}
ฉันนำโซลูชันที่แนะนำโดย @ (Kirk Woll) มาใช้งานได้สำหรับฉัน ฉันเห็นด้วยในซอร์สโค้ด Android สำหรับแอป "ผู้ติดต่อ" ว่าพวกเขาใช้เทคนิคที่คล้ายกัน ฉันต้องการที่จะเพิ่มรายละเอียดเพิ่มเติม: ด้านบนของชั้น ListActivity ของฉัน:
private static final String LIST_STATE = "listState";
private Parcelable mListState = null;
จากนั้นวิธีการบางอย่างแทนที่:
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
mListState = state.getParcelable(LIST_STATE);
}
@Override
protected void onResume() {
super.onResume();
loadData();
if (mListState != null)
getListView().onRestoreInstanceState(mListState);
mListState = null;
}
@Override
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
mListState = getListView().onSaveInstanceState();
state.putParcelable(LIST_STATE, mListState);
}
แน่นอน "loadData" เป็นฟังก์ชั่นของฉันเพื่อดึงข้อมูลจากฐานข้อมูลและวางลงในรายการ
บนอุปกรณ์ Froyo ของฉันสิ่งนี้ใช้ได้ทั้งเมื่อคุณเปลี่ยนการวางแนวโทรศัพท์และเมื่อคุณแก้ไขรายการแล้วกลับไปที่รายการ
mListState = getListView().onSaveInstanceState().
ส่วนใหญ่เกี่ยวกับการหมุนอุปกรณ์
onRestoreInstanceState
ไม่เคยถูกเรียกว่า :(
วิธีที่ง่ายมาก:
/** Save the position **/
int currentPosition = listView.getFirstVisiblePosition();
//Here u should save the currentPosition anywhere
/** Restore the previus saved position **/
listView.setSelection(savedPosition);
วิธีsetSelectionจะรีเซ็ตรายการเป็นรายการที่ให้มา หากไม่ได้อยู่ในโหมดสัมผัสรายการนั้นจะถูกเลือกจริงหากอยู่ในโหมดสัมผัสรายการนั้นจะถูกจัดวางบนหน้าจอเท่านั้น
แนวทางที่ซับซ้อนมากขึ้น:
listView.setOnScrollListener(this);
//Implements the interface:
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mCurrentX = view.getScrollX();
mCurrentY = view.getScrollY();
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
//Save anywere the x and the y
/** Restore: **/
listView.scrollTo(savedX, savedY);
ฉันพบสิ่งที่น่าสนใจเกี่ยวกับสิ่งนี้
ฉันลอง setSelection และ scrolltoXY แต่มันไม่ทำงานเลยรายการยังคงอยู่ในตำแหน่งเดิมหลังจากการทดลองและข้อผิดพลาดฉันได้รับรหัสต่อไปนี้ที่ใช้งานได้
final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {
@Override
public void run() {
list.setSelection(0);
}
});
ถ้าแทนที่จะโพสต์ Runnable คุณลอง runOnUiThread มันไม่ทำงาน (อย่างน้อยในบางอุปกรณ์)
นี่เป็นวิธีแก้ปัญหาที่แปลกมากสำหรับบางสิ่งที่ควรตรงไป
setSelectionFromTop()
ไม่ทำงาน
ข้อควรระวัง !! มีข้อผิดพลาดใน AbsListView ที่ไม่อนุญาตให้ onSaveState () ทำงานอย่างถูกต้องหาก ListView.getFirstVisiblePosition () เป็น 0
ดังนั้นหากคุณมีภาพขนาดใหญ่ที่ใช้หน้าจอส่วนใหญ่และคุณเลื่อนไปที่ภาพที่สอง แต่ภาพแรก ๆ ที่แสดงอยู่ตำแหน่งเลื่อนจะไม่ถูกบันทึก ...
จากAbsListView.java:1650 (ความเห็นของฉัน)
// this will be false when the firstPosition IS 0
if (haveChildren && mFirstPosition > 0) {
...
} else {
ss.viewTop = 0;
ss.firstId = INVALID_POSITION;
ss.position = 0;
}
แต่ในสถานการณ์นี้ 'อันดับสูงสุด' ในรหัสด้านล่างจะเป็นจำนวนลบซึ่งทำให้เกิดปัญหาอื่น ๆ ที่ทำให้ไม่สามารถเรียกคืนสถานะได้อย่างถูกต้อง ดังนั้นเมื่อ 'ด้านบน' เป็นลบให้รับลูกคนถัดไป
// save index and top position
int index = getFirstVisiblePosition();
View v = getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
if (top < 0 && getChildAt(1) != null) {
index++;
v = getChildAt(1);
top = v.getTop();
}
// parcel the index and top
// when restoring, unparcel index and top
listView.setSelectionFromTop(index, top);
private Parcelable state;
@Override
public void onPause() {
state = mAlbumListView.onSaveInstanceState();
super.onPause();
}
@Override
public void onResume() {
super.onResume();
if (getAdapter() != null) {
mAlbumListView.setAdapter(getAdapter());
if (state != null){
mAlbumListView.requestFocus();
mAlbumListView.onRestoreInstanceState(state);
}
}
}
เพียงพอ
สำหรับบางคนที่กำลังมองหาวิธีแก้ไขปัญหานี้รากของปัญหาอาจเป็นที่ที่คุณกำลังตั้งค่าอะแด็ปเตอร์มุมมองรายการของคุณ หลังจากที่คุณตั้งค่าการ์ดเชื่อมต่อใน listview มันจะรีเซ็ตตำแหน่งการเลื่อน สิ่งที่ต้องพิจารณา ฉันย้ายการตั้งค่าอะแดปเตอร์ไปที่ onCreateView ของฉันหลังจากที่เราทำการอ้างอิงไปยัง listview และมันแก้ปัญหาให้ฉันได้ =)
ฉันกำลังโพสต์สิ่งนี้เพราะฉันประหลาดใจที่ไม่มีใครพูดถึงเรื่องนี้
หลังจากผู้ใช้คลิกปุ่มย้อนกลับเขาจะกลับไปที่ listview ในสถานะเดียวกับที่เขาออกไป
รหัสนี้จะแทนที่ปุ่ม "up" เพื่อทำงานในลักษณะเดียวกับปุ่มย้อนกลับในกรณีของ Listview -> Details -> Back to Listview (และไม่มีตัวเลือกอื่น ๆ ) นี่เป็นรหัสที่ง่ายที่สุดในการรักษา scrollposition และเนื้อหา ในมุมมองรายการ
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return(true);
}
return(super.onOptionsItemSelected(item)); }
ข้อควรระวัง: หากคุณสามารถไปที่กิจกรรมอื่นจากกิจกรรมรายละเอียดปุ่มขึ้นจะนำคุณกลับสู่กิจกรรมนั้นดังนั้นคุณจะต้องจัดการประวัติย้อนกลับเพื่อให้สิ่งนี้ทำงานได้
ไม่ได้เป็นเพียงแค่android:saveEnabled="true"
ใน ListView XML ประกาศเพียงพอหรือไม่
ทางออกที่ดีที่สุดคือ:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
// ...
// restore index and position
mList.post(new Runnable() {
@Override
public void run() {
mList.setSelectionFromTop(index, top);
}
});
คุณต้องโทรในโพสต์และในกระทู้!
คุณสามารถรักษาสถานะการเลื่อนหลังจากโหลดใหม่ได้หากคุณบันทึกสถานะก่อนที่จะโหลดซ้ำและกู้คืนหลังจากนั้น ในกรณีของฉันฉันทำการร้องขอเครือข่ายแบบอะซิงโครนัสและโหลดรายการในการติดต่อกลับหลังจากเสร็จสิ้น นี่คือที่ฉันเรียกคืนสถานะ ตัวอย่างโค้ดคือ Kotlin
val state = myList.layoutManager.onSaveInstanceState()
getNewThings() { newThings: List<Thing> ->
myList.adapter.things = newThings
myList.layoutManager.onRestoreInstanceState(state)
}
หากคุณใช้แฟรกเมนต์ที่โฮสต์ในกิจกรรมคุณสามารถทำสิ่งนี้ได้:
public abstract class BaseFragment extends Fragment {
private boolean mSaveView = false;
private SoftReference<View> mViewReference;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mSaveView) {
if (mViewReference != null) {
final View savedView = mViewReference.get();
if (savedView != null) {
if (savedView.getParent() != null) {
((ViewGroup) savedView.getParent()).removeView(savedView);
return savedView;
}
}
}
}
final View view = inflater.inflate(getFragmentResource(), container, false);
mViewReference = new SoftReference<View>(view);
return view;
}
protected void setSaveView(boolean value) {
mSaveView = value;
}
}
public class MyFragment extends BaseFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setSaveView(true);
final View view = super.onCreateView(inflater, container, savedInstanceState);
ListView placesList = (ListView) view.findViewById(R.id.places_list);
if (placesList.getAdapter() == null) {
placesList.setAdapter(createAdapter());
}
}
}
หากคุณกำลังบันทึก / กู้คืนตำแหน่งการเลื่อนของListView
ตัวคุณเองคุณกำลังทำซ้ำฟังก์ชั่นการใช้งานแล้วในกรอบ Android การListView
คืนค่าตำแหน่งการเลื่อนที่ดีเพียงอย่างเดียวของตัวเองยกเว้นหนึ่ง caveat: @aaronvargas ที่กล่าวถึงมีข้อผิดพลาดAbsListView
ที่จะไม่อนุญาตให้กู้คืนตำแหน่งการเลื่อนที่ดีสำหรับรายการแรก อย่างไรก็ตามวิธีที่ดีที่สุดในการกู้คืนตำแหน่งการเลื่อนไม่ใช่เพื่อกู้คืน เฟรมเวิร์ก Android จะทำดีกว่าสำหรับคุณ เพียงตรวจสอบให้แน่ใจว่าคุณปฏิบัติตามเงื่อนไขต่อไปนี้แล้ว:
setSaveEnabled(false)
ใช้เมธอดและไม่ได้ตั้งค่าแอandroid:saveEnabled="false"
ททริบิวสำหรับรายการในไฟล์เลย์เอาต์ xmlExpandableListView
แทนที่long getCombinedChildId(long groupId, long childId)
เพื่อให้มันส่งกลับจำนวนยาวบวก (การใช้งานเริ่มต้นในชั้นเรียนBaseExpandableListAdapter
ส่งกลับจำนวนลบ) นี่คือตัวอย่าง:.
@Override
public long getChildId(int groupPosition, int childPosition) {
return 0L | groupPosition << 12 | childPosition;
}
@Override
public long getCombinedChildId(long groupId, long childId) {
return groupId << 32 | childId << 1 | 1;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getCombinedGroupId(long groupId) {
return (groupId & 0x7FFFFFFF) << 32;
}
ListView
หรือExpandableListView
ใช้ในแฟรกเมนต์อย่าสร้างแฟรกเมนต์ใหม่ในกิจกรรมสันทนาการ (เช่นหลังจากการหมุนหน้าจอเป็นต้น) รับแฟรกเมนต์ด้วยfindFragmentByTag(String tag)
เมธอดListView
มีandroid:id
และมันเป็นเอกลักษณ์เพื่อหลีกเลี่ยงข้อแม้ดังกล่าวกับรายการแรกคุณสามารถสร้างอะแดปเตอร์ของคุณวิธีที่มันกลับมุมมองความสูงพิกเซลศูนย์หุ่นจำลองสำหรับListView
ตำแหน่งที่ 0 นี่คือตัวอย่างโครงการที่เรียบง่ายแสดงListView
และExpandableListView
เรียกคืนตำแหน่งเลื่อนที่ดีในขณะที่ตำแหน่งเลื่อนของพวกเขา / การบูรณะ ตำแหน่งการเลื่อนที่ละเอียดถูกเรียกคืนได้อย่างสมบูรณ์แบบแม้ในสถานการณ์ที่ซับซ้อนด้วยการสลับไปยังแอปพลิเคชั่นอื่นชั่วคราวการหมุนหน้าจอสองเท่าและการสลับกลับไปที่แอปพลิเคชันทดสอบ โปรดทราบว่าหากคุณออกจากแอปพลิเคชั่นอย่างชัดเจน (โดยการกดปุ่มย้อนกลับ) ตำแหน่งการเลื่อนจะไม่ถูกบันทึก (เช่นเดียวกับมุมมองอื่น ๆ ทั้งหมดจะไม่บันทึกสถานะ)
https://github.com/voromto/RestoreScrollPosition/releases
สำหรับกิจกรรมที่ได้รับจาก ListActivity ที่ใช้ LoaderManager.LoaderCallbacks โดยใช้ SimpleCursorAdapter มันไม่ทำงานเพื่อกู้คืนตำแหน่งใน onReset () เนื่องจากกิจกรรมถูกรีสตาร์ทเกือบทุกครั้งและอะแดปเตอร์ถูกโหลดใหม่เมื่อมุมมองรายละเอียดถูกปิด เคล็ดลับคือการกู้คืนตำแหน่งใน onLoadFinished ():
ใน onListItemClick ():
// save the selected item position when an item was clicked
// to open the details
index = getListView().getFirstVisiblePosition();
View v = getListView().getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - getListView().getPaddingTop());
ใน onLoadFinished ():
// restore the selected item which was saved on item click
// when details are closed and list is shown again
getListView().setSelectionFromTop(index, top);
ใน onBackPressed ():
// Show the top item at next start of the app
index = 0;
top = 0;
วิธีแก้ปัญหาที่เสนอที่นี่ดูเหมือนจะไม่เหมาะกับฉัน ในกรณีของฉันฉันมีListView
ในFragment
ที่ฉันเปลี่ยนในFragmentTransaction
ดังนั้นใหม่Fragment
เช่นจะถูกสร้างขึ้นในแต่ละครั้งส่วนจะแสดงซึ่งหมายความว่ารัฐไม่สามารถเก็บไว้ในฐานะสมาชิกของListView
Fragment
แต่ฉันจบลงด้วยการจัดเก็บสถานะในApplication
ชั้นเรียนที่กำหนดเองของฉัน รหัสด้านล่างควรให้แนวคิดแก่คุณเกี่ยวกับวิธีการทำงานของ
public class MyApplication extends Application {
public static HashMap<String, Parcelable> parcelableCache = new HashMap<>();
/* ... code omitted for brevity ... */
}
public class MyFragment extends Fragment{
private ListView mListView = null;
private MyAdapter mAdapter = null;
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAdapter = new MyAdapter(getActivity(), null, 0);
mListView = ((ListView) view.findViewById(R.id.myListView));
Parcelable listViewState = MyApplication.parcelableCache.get("my_listview_state");
if( listViewState != null )
mListView.onRestoreInstanceState(listViewState);
}
@Override
public void onPause() {
MyApplication.parcelableCache.put("my_listview_state", mListView.onSaveInstanceState());
super.onPause();
}
/* ... code omitted for brevity ... */
}
แนวคิดพื้นฐานคือคุณเก็บสถานะไว้นอกอินสแตนซ์แฟรกเมนต์ หากคุณไม่ชอบความคิดในการมีฟิลด์แบบสแตติกในคลาสแอปพลิเคชันของคุณฉันคิดว่าคุณสามารถทำได้โดยการใช้ส่วนอินเตอร์เฟสและจัดเก็บสถานะในกิจกรรมของคุณ
วิธีแก้ปัญหาอื่นก็คือการเก็บไว้ในSharedPreferences
นั้น แต่มันก็ซับซ้อนขึ้นเล็กน้อยและคุณจะต้องทำให้แน่ใจว่าคุณเคลียร์มันในการเปิดตัวแอพพลิเคชั่นถ้าคุณไม่ต้องการให้สถานะคงอยู่ตลอดการเปิดตัวแอพ
นอกจากนี้เพื่อหลีกเลี่ยง "ตำแหน่งการเลื่อนที่ไม่ได้บันทึกเมื่อมองเห็นรายการแรก" คุณสามารถแสดงรายการแรกที่มี0px
ความสูงได้ สามารถทำได้โดยเอาชนะgetView()
ในอะแดปเตอร์ของคุณเช่นนี้
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if( position == 0 ) {
View zeroHeightView = new View(parent.getContext());
zeroHeightView.setLayoutParams(new ViewGroup.LayoutParams(0, 0));
return zeroHeightView;
}
else
return super.getView(position, convertView, parent);
}
คำตอบของฉันคือ Firebase และตำแหน่ง 0 เป็นวิธีแก้ปัญหา
Parcelable state;
DatabaseReference everybody = db.getReference("Everybody Room List");
everybody.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
state = listView.onSaveInstanceState(); // Save
progressBar.setVisibility(View.GONE);
arrayList.clear();
for (DataSnapshot messageSnapshot : dataSnapshot.getChildren()) {
Messages messagesSpacecraft = messageSnapshot.getValue(Messages.class);
arrayList.add(messagesSpacecraft);
}
listView.setAdapter(convertView);
listView.onRestoreInstanceState(state); // Restore
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
และ convertView
ตำแหน่ง 0 เพิ่มรายการว่างที่คุณไม่ได้ใช้
public class Chat_ConvertView_List_Room extends BaseAdapter {
private ArrayList<Messages> spacecrafts;
private Context context;
@SuppressLint("CommitPrefEdits")
Chat_ConvertView_List_Room(Context context, ArrayList<Messages> spacecrafts) {
this.context = context;
this.spacecrafts = spacecrafts;
}
@Override
public int getCount() {
return spacecrafts.size();
}
@Override
public Object getItem(int position) {
return spacecrafts.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@SuppressLint({"SetTextI18n", "SimpleDateFormat"})
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.message_model_list_room, parent, false);
}
final Messages s = (Messages) this.getItem(position);
if (position == 0) {
convertView.getLayoutParams().height = 1; // 0 does not work
} else {
convertView.getLayoutParams().height = RelativeLayout.LayoutParams.WRAP_CONTENT;
}
return convertView;
}
}
ฉันได้เห็นงานนี้เป็นการชั่วคราวโดยไม่รบกวนผู้ใช้ฉันหวังว่าจะได้ผลกับคุณ
ใช้รหัสด้านล่างนี้:
int index,top;
@Override
protected void onPause() {
super.onPause();
index = mList.getFirstVisiblePosition();
View v = challengeList.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
}
และเมื่อใดก็ตามที่รีเฟรชข้อมูลของคุณให้ใช้โค้ดด้านล่างนี้:
adapter.notifyDataSetChanged();
mList.setSelectionFromTop(index, top);
ฉันใช้FirebaseListAdapterและไม่สามารถแก้ไขปัญหาได้ ในที่สุดฉันก็ลงมือทำสิ่งนี้ ฉันเดาว่ามันมีวิธีที่สง่างามกว่า แต่มันก็เป็นโซลูชั่นที่สมบูรณ์และใช้งานได้
ก่อนหน้านี้สร้าง:
private int reset;
private int top;
private int index;
ด้านในของ FirebaseListAdapter:
@Override
public void onDataChanged() {
super.onDataChanged();
// Only do this on first change, when starting
// activity or coming back to it.
if(reset == 0) {
mListView.setSelectionFromTop(index, top);
reset++;
}
}
onStart:
@Override
protected void onStart() {
super.onStart();
if(adapter != null) {
adapter.startListening();
index = 0;
top = 0;
// Get position from SharedPrefs
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
top = sharedPref.getInt("TOP_POSITION", 0);
index = sharedPref.getInt("INDEX_POSITION", 0);
// Set reset to 0 to allow change to last position
reset = 0;
}
}
onStop:
@Override
protected void onStop() {
super.onStop();
if(adapter != null) {
adapter.stopListening();
// Set position
index = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - mListView.getPaddingTop());
// Save position to SharedPrefs
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
}
}
เนื่องจากฉันต้องแก้ปัญหานี้สำหรับFirebaseRecyclerAdapterฉันกำลังโพสต์โซลูชันที่นี่เช่นกัน:
ก่อนหน้านี้สร้าง:
private int reset;
private int top;
private int index;
ภายใน FirebaseRecyclerAdapter:
@Override
public void onDataChanged() {
// Only do this on first change, when starting
// activity or coming back to it.
if(reset == 0) {
linearLayoutManager.scrollToPositionWithOffset(index, top);
reset++;
}
}
onStart:
@Override
protected void onStart() {
super.onStart();
if(adapter != null) {
adapter.startListening();
index = 0;
top = 0;
// Get position from SharedPrefs
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
top = sharedPref.getInt("TOP_POSITION", 0);
index = sharedPref.getInt("INDEX_POSITION", 0);
// Set reset to 0 to allow change to last position
reset = 0;
}
}
onStop:
@Override
protected void onStop() {
super.onStop();
if(adapter != null) {
adapter.stopListening();
// Set position
index = linearLayoutManager.findFirstVisibleItemPosition();
View v = linearLayoutManager.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
// Save position to SharedPrefs
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
sharedPref.edit().putInt("TOP_POSITION" + "", top).apply();
sharedPref.edit().putInt("INDEX_POSITION" + "", index).apply();
}
}
เพื่อชี้แจงคำตอบที่ดีเยี่ยมของRyan Newsomและปรับแก้สำหรับชิ้นส่วนและสำหรับกรณีปกติที่เราต้องการนำทางจากส่วน "หลัก" ListView เป็นชิ้นส่วน "รายละเอียด" จากนั้นกลับไปที่ "หลัก"
private View root;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
if(root == null){
root = inflater.inflate(R.layout.myfragmentid,container,false);
InitializeView();
}
return root;
}
public void InitializeView()
{
ListView listView = (ListView)root.findViewById(R.id.listviewid);
BaseAdapter adapter = CreateAdapter();//Create your adapter here
listView.setAdpater(adapter);
//other initialization code
}
"เวทมนต์" ที่นี่คือเมื่อเรานำทางกลับจากส่วนรายละเอียดไปยังส่วน ListView มุมมองที่ไม่ได้สร้างขึ้นใหม่เราไม่ได้ตั้งอะแดปเตอร์ของ ListView ดังนั้นทุกอย่างยังคงอยู่ในขณะที่เราทิ้งไว้!