তালিকাভিউতে ফিরে আসার পরে / সংরক্ষণ / পুনরুদ্ধারের স্ক্রোল অবস্থান


397

আমার দীর্ঘ রয়েছে ListViewযা ব্যবহারকারী আগের স্ক্রিনে ফিরে আসার আগে চারদিকে স্ক্রোল করতে পারে। যখন ব্যবহারকারী এটি ListViewআবার খুলবে , আমি চাই তালিকাটি একই পয়েন্টে স্ক্রোল করা যাতে এটি আগে ছিল। কীভাবে এটি অর্জন করতে পারে তার কোনও ধারণা?


22
আমি মনে করি ইউজিন মাইমরিন / জর্জিও বারচিয়েসির দ্বারা বর্ণিত সমাধানগুলি গৃহীত উত্তরের চেয়ে ভাল
মীরা ওয়েলার

উত্তর:


631

এটা চেষ্টা কর:

// 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এর স্ক্রোল অবস্থানটি পুনরুদ্ধার করতে , আমরা ListView.setSelectionFromTop()যে আইটেমটি চাই তার সূচক এবং একটি অফসেট এর শীর্ষ প্রান্তটি শীর্ষের দিক থেকে অবস্থিত করে কল করি ListView


2
এটি কীভাবে কাজ করে তা সত্যই বুঝতে পারছি না। আমি কেবল তালিকাভিউ.জেটফর্স্টভিজিবল পজিশন () ব্যবহার করছি এবং এটি বুঝতে পারি, তবে এখানে কী চলছে তা নিশ্চিত নয়। সংক্ষিপ্ত ব্যাখ্যার কোনও সুযোগ? :)
এইচএক্সকেইন

56
সুতরাং তালিকার ভিউ.সেট ফার্স্টভিজিবল অবস্থান () শীর্ষস্থানীয় দৃশ্যমান তালিকা আইটেমটি প্রদান করে। তবে এই আইটেমটি আংশিকভাবে দেখার বাইরে স্ক্রোল করা হতে পারে এবং আপনি যদি তালিকার সঠিক স্ক্রোল অবস্থানটি পুনরুদ্ধার করতে চান তবে আপনার এই অফসেটটি পেতে হবে। সুতরাং তালিকাভিউ.গেটচিল্ডটি (0) শীর্ষ তালিকার আইটেমটির জন্য ভিউটি প্রদান করে এবং তারপরে View.getTop () তালিকাভুক্তির শীর্ষ থেকে তার সম্পর্কিত অফসেটটি ফিরিয়ে দেয়। তারপরে, তালিকার ভিউর স্ক্রোলের অবস্থানটি পুনরুদ্ধার করার জন্য, আমরা যে আইটেমটি চাই তার সূচি সহ তালিকাভিউ.সেটস্লেইশনফ্রোমটপ () কে কল করি এবং একটি অফসেট তালিকাগুলির শীর্ষ থেকে তার শীর্ষ প্রান্তটি স্থাপন করে। সব পরিষ্কার?
আইয়ান

15
এই সংরক্ষণ করতে এক লাইন ব্যবহার করা এমনকি সহজ তৈরি করা যেতে পারে int index = mList.getFirstVisiblePosition();পুনঃস্থাপন এবং শুধুমাত্র এক লাইন: mList.setSelectionFromTop(index, 0);। দুর্দান্ত উত্তর যদিও (+1)! আমি এই সমস্যার একটি মার্জিত সমাধান খুঁজছি।
ফিল

17
@ ফিল আপনার সরলিক সমাধান সঠিক স্ক্রোলিং অবস্থান পুনরুদ্ধার করতে কাজ করে না।
আইএক্সএক্স

2
যেমনটি @nbarraille বলেছেন, কোডটি "v.getTop () - mList.getPaddingTop ()" এর মতো আরও পড়তে হবে। অন্যথায় আপনি এক ঘন্টা ব্যয় করবেন যেমন আমি কেন সবসময় কেবল একটি চুল বন্ধ করে
রাখি তা জানার চেষ্টা করেছি

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

106
আমি মনে করি এটি সেরা উত্তর কারণ এই পদ্ধতিটি সঠিক স্ক্রোল অবস্থানটি পুনরুদ্ধার করে এবং কেবল প্রথম দৃশ্যমান আইটেমটিই নয়।
মীরা ওয়েলার

9
দুর্দান্ত উত্তর কিন্তু কার্যকর হবে না যখন গতিশীল কন্টেন্ট লোড হয় এবং আপনি অনপজ () পদ্ধতিতে রাষ্ট্র সংরক্ষণ করতে চান।
জিও

13
দুর্দান্ত সমাধান কেবল একটি সমস্যা। যদি আইটেমগুলি বড় হয় এবং আপনি স্ক্রোল করেন তবে প্রথম আইটেমটি এখনও দৃশ্যমান হয় তালিকার শীর্ষে ফিরে আসে। আপনি যদি দ্বিতীয় আইটেমে বা অন্য কোথাও যে কোনও কিছুতে স্ক্রোল করে
34

4
@ পাসসি আপনি কি শীর্ষে ফিরে লাফিয়ে তালিকার কোনও সমাধান খুঁজে পেয়েছেন?
পাপাজোহন000

2
অ্যারোনভার্গাস যেমন বলেছে, তালিকাভিউ.জেটফার্সটিভিজিবল পজিশন () 0 হয় তখন এটি কাজ করতে পারে না
ভিন্সস্টাইলিং

54

আমি @ (কার্ক ওল) এর প্রস্তাবিত সমাধানটি গ্রহণ করেছি এবং এটি আমার পক্ষে কাজ করে। "পরিচিতি" অ্যাপ্লিকেশনটির জন্য আমি অ্যান্ড্রয়েড উত্স কোডেও দেখেছি যে তারা অনুরূপ কৌশল ব্যবহার করে। আমি আরও কিছু বিশদ যুক্ত করতে চাই: আমার তালিকাগুলি থেকে প্রাপ্ত ক্লাসের শীর্ষে:

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

অবশ্যই "লোডডাটা" হ'ল ডিবি থেকে ডেটা পুনরুদ্ধার এবং এটি তালিকায় রাখার জন্য আমার কাজ।

আমার ফ্রয়েও ডিভাইসে, আপনি যখন ফোন ওরিয়েন্টেশন পরিবর্তন করেন এবং আপনি যখন কোনও আইটেম সম্পাদনা করেন এবং তালিকায় ফিরে যান তখন এটি উভয়ই কার্যকর হয়।


1
এই সমাধানটি আমার পক্ষে কাজ করেছিল। অন্যরা তা করেনি। তালিকাভিউ দৃষ্টান্তের স্টেটিকে সংরক্ষণ / পুনরুদ্ধার কীভাবে তালিকাভিউতে আইটেমগুলি মোছা বা সন্নিবেশ করার ক্ষেত্রে আচরণ করে?
ব্রায়ান

2
এফওয়াইআই যদি আপনি এটি কোনও খণ্ডে ব্যবহার করেন (আমি একটি তালিকার টুকরোটি ব্যবহার করছি) এবং অন্যান্য খণ্ডগুলিতে নেভিগেট করেন তবে এটি ক্র্যাশ হয়ে যাবে কারণ mListState = getListView().onSaveInstanceState().মূলত ডিভাইস রোটেশনে কল করার সময় সামগ্রীটি তৈরি করা হয়নি ।
এমগামেরজ

2
onRestoreInstanceStateকখনই ডাকা হয় না :(
ডিভ্যাফিকেশন

1
@ জিয়েরজিও বারচিয়েসি @ কে (কার্ক উল) যার সমাধান আপনার পক্ষে কাজ করে? ব্যবহারকারী দৃশ্যত তার নাম পরিবর্তন করেছেন changed
পাইওজান

1
হ্যাঁ, এটি সরকারী ধর্ম। তবে আমার ক্ষেত্রে ডেটা স্থানীয়ভাবে লোড হয়, এর দৈর্ঘ্য খুব কম থাকে এবং একটি বিভাজনে দ্বিতীয়টি লোড হয়, তাই আমি প্রাকৃতিকভাবে গিয়েছিলাম :-)
জর্জিও বার্চিয়েসি

26

খুব সহজ উপায়:

/** Save the position **/
int currentPosition = listView.getFirstVisiblePosition();

//Here u should save the currentPosition anywhere

/** Restore the previus saved position **/
listView.setSelection(savedPosition);

পদ্ধতি সেটস্লেশন সরবরাহ করা আইটেমটিতে তালিকাটি পুনরায় সেট করবে। টাচ মোডে না থাকলে আইটেমটি আসলে নির্বাচিত হবে যদি টাচ মোডে আইটেমটি কেবলমাত্র স্ক্রিনে অবস্থান করে।

আরও জটিল পদ্ধতির:

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

2
আপনার উত্তরে একটি ত্রুটি ছিল। পদ্ধতি setSelection বলা হয়
Janusz

ধারণাটি ভালভাবে কাজ করে তবে একটি ছদ্ম সমস্যা রয়েছে first প্রণীত।
রন্ট্রাভি

আমার দ্বিতীয় বিকল্পটি একবার দেখুন। আমি কেবল এটি আমার প্রথম উত্তরে যুক্ত করেছি
ফ্রান্সেস্কো লরিটা

27
দেখুন.getScrolX () এবং দেখুন.getScrolY () সর্বদা 0 ফেরত!
রেন্ট্রাভি

3
View.getChildAt () এবং View.getTop () ব্যবহার করে উপরে আমার (স্বীকৃত) সমাধানটি দেখুন। আপনি তালিকাভিউতে View.getScrolY () ব্যবহার করতে পারবেন না কারণ একটি তালিকাভিউ অভ্যন্তরীণভাবে তার স্ক্রোলিং বজায় রাখে।
আইয়ান

17

আমি এই সম্পর্কে আকর্ষণীয় কিছু পেয়েছি।

আমি সেটলেশন এবং স্ক্রোলটএক্সওয়াই চেষ্টা করেছি কিন্তু এটি মোটেই কার্যকর হয়নি, তালিকাটি একই অবস্থানে থেকেছে, কিছু পরীক্ষার এবং ত্রুটির পরে আমি নিম্নলিখিত কোড পেয়েছি যা কাজ করে

final ListView list = (ListView) findViewById(R.id.list);
list.post(new Runnable() {            
    @Override
    public void run() {
        list.setSelection(0);
    }
});

রান্নেবল পোস্ট করার পরিবর্তে আপনি রানঅনউইথ্রেড চেষ্টা করুন এটি কোনওভাবেই কাজ করে না (কমপক্ষে কিছু ডিভাইসে)

এটি এমন কোনও কিছুর জন্য খুব বিস্ময়কর কাজ যা সরাসরি এগিয়ে আসা উচিত।


1
আমি একই সমস্যা অভিজ্ঞতা! এবং setSelectionFromTop()কাজ করে না।
ofavre

+1 টি। listnew.post (), কিছু ডিভাইসে কাজ করে না এবং কিছু অন্যান্য ডিভাইসে এটি কিছু ক্ষেত্রে কার্যকর হয় না, তবে রানঅনউইথথ দুর্দান্ত কাজ করে।
ওমর রেহমান

@ ওমর, আপনি কি ডিভাইস এবং ওএসের কিছু উদাহরণ দিতে পারেন যা এটি কাজ করে না? আমি একটি এইচটিসি জি 2 (2.3.4) এবং একটি গ্যালাক্সি নেক্সাস (4.1.2) চেষ্টা করেছি এবং এটি উভয় ক্ষেত্রেই কাজ করেছে। এই থ্রেডের অন্য কোনও উত্তর আমার কোনও ডিভাইসের জন্য কাজ করে নি।
ড্যান জে

2
listview.post আমার গ্যালাক্সি নোটে 4.0.4 দিয়ে সূক্ষ্মভাবে কাজ করে, তবে আমার নেক্সাস ওনে 2.3.6 দিয়ে কাজ করে না। তবে, অনউইথ্রেড (ক্রিয়া) উভয় ডিভাইসে সূক্ষ্মভাবে কাজ করে।
ওমর রেহমান

11

সতর্ক করা!! অ্যাবস্লিস্টভিউতে একটি বাগ রয়েছে যা তালিকাভিউ.জেটফর্স্টভিজিবলপজিশন () 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);

এটি একটি কবজির মতো কাজ করে তবে আমি এটি পুরোপুরি বুঝতে পারি না। যদি প্রথম আইটেমটি এখনও দৃশ্যমান হয়, তবে পরবর্তী সন্তানের প্রাপ্তিটি কীভাবে বোঝায়? নতুন সূচকের সাথে সিলিফিকেশন ফ্রমটপ সেটটি দ্বিতীয় সন্তানের থেকে শুরু করে দেখানো উচিত নয়? আমি এখনও প্রথমটি কীভাবে দেখছি?
তাফি

@ টাফি, প্রথম আইটেমটি 'আংশিক' দৃশ্যমান হতে পারে। সুতরাং এই আইটেমের শীর্ষটি পর্দার উপরে হবে এবং এইভাবে একটি নেতিবাচক সংখ্যা হবে। (এটি অন্যান্য সমস্যার মুখোমুখি হয় না যা আমি স্মরণ করি না ...) সুতরাং আমরা দ্বিতীয় আইটেমের 'শীর্ষ' ব্যবহার করি প্লেসমেন্টের জন্য, যা সর্বদা (?) পাওয়া উচিত, অথবা সেখানে প্রথম কোনও স্ক্রোলিং হবে না !
অ্যারোনভার্গাস

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

তাতেই চলবে


হাই, আপনার উপরের কোডগুলি কি আমাকে পুনর্ব্যবহারযোগ্য তালিকাতে সহায়তা করবে যেখানে ক্রিয়াকলাপগুলির মধ্যে উদাহরণস্বরূপ সংরক্ষণ করা হচ্ছে না? আমি নীচের প্রশ্নটি এখানে পোস্ট করেছি: স্ট্যাকওভারফ্লো . com/ জিজ্ঞাসা / 35413495/… ?
এজেডাব্লু

6

কারও কারও কাছে এই সমস্যার সমাধানের সন্ধানের জন্য, ইস্যুটির মূলটি এমন হতে পারে যেখানে আপনি নিজের তালিকা দর্শন অ্যাডাপ্টার সেট করছেন। আপনি তালিকা ভিউতে অ্যাডাপ্টার সেট করার পরে, এটি স্ক্রোল অবস্থানটি পুনরায় সেট করে। কিছু বিবেচনা করার জন্য। আমরা তালিকা দর্শনের রেফারেন্সটি ধরার পরে আমি আমার অনক্রিটভিউতে অ্যাডাপ্টারটি সেট করেছিলাম এবং এটি আমার জন্য সমস্যার সমাধান করে। =)


1

এটি পোস্ট করছি কারণ আমি অবাক হয়েছি যে কেউ এটি উল্লেখ করেনি।

ব্যবহারকারীর পিছনে বোতামটি ক্লিক করার পরে তিনি তালিকা থেকে বেরিয়ে যাওয়ার সাথে সাথে একই অবস্থায় তালিকায় ফিরে আসবেন।

এই কোডটি "আপ" বোতামটি ওভাররাইড করবে যেমন পিছনের বোতামের মতো আচরণ করতে হবে তাই তালিকার ভিউ -> বিশদ -> তালিকায় ফিরে যান (এবং অন্য কোনও বিকল্প নেই) এই স্ক্রোলপজিশন এবং বিষয়বস্তু বজায় রাখার জন্য সহজতম কোড is তালিকায়।

 public boolean onOptionsItemSelected(MenuItem item) {
     switch (item.getItemId()) {
         case android.R.id.home:
             onBackPressed();
             return(true);
     }
     return(super.onOptionsItemSelected(item)); }

সতর্কতা: আপনি যদি বিশদ ক্রিয়াকলাপ থেকে অন্য ক্রিয়াকলাপে যেতে পারেন তবে আপ বোতামটি আপনাকে সেই ক্রিয়াকলাপে ফিরিয়ে আনবে যাতে এটি কাজ করার জন্য আপনাকে ব্যাকবটন ইতিহাসের কৌশলটি পরিচালনা করতে হবে ulate


1

কেবলমাত্র android:saveEnabled="true"তালিকাভিউ এক্সএমএল ঘোষণায় যথেষ্ট নয়?


1
অ্যান্ড্রয়েড: saveEn सक्षम ডিফল্টরূপে সত্য সেট করা আছে to এটি কিছুই করে না।
ব্র্যাড

কোন। যে যথেষ্ট নয়, আপনাকে অনুসরণ করতে হবে stackoverflow.com/questions/3014089/... বা stackoverflow.com/questions/3014089/...
রাহুল Mandaliya

1

সেরা সমাধান হল:

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

আপনি পোষ্ট এবং থ্রেড কল করা উচিত!


1

আপনি যদি পুনরায় লোড করার আগে রাষ্ট্রটি সংরক্ষণ করেন এবং এর পরে পুনরুদ্ধার করেন তবে আপনি পুনরায় লোডের পরে স্ক্রোলের স্থিতি বজায় রাখতে পারেন। আমার ক্ষেত্রে আমি একটি অ্যাসিক্রোনাস নেটওয়ার্ক অনুরোধ করেছি এবং তালিকাটি শেষ হওয়ার পরে কলব্যাকে পুনরায় লোড করেছি। এখানেই আমি রাষ্ট্র পুনরুদ্ধার করি। কোড নমুনা হ'ল কোটলিন।

val state = myList.layoutManager.onSaveInstanceState()

getNewThings() { newThings: List<Thing> ->

    myList.adapter.things = newThings
    myList.layoutManager.onRestoreInstanceState(state)
}

0

আপনি যদি কোনও ক্রিয়াকলাপে হোস্ট করা টুকরো ব্যবহার করে থাকেন তবে আপনি এই জাতীয় কিছু করতে পারেন:

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

0

আপনি যদি ListViewনিজের স্ক্রোলের অবস্থান সংরক্ষণ / পুনরুদ্ধার করছেন তবে আপনি অ্যান্ড্রয়েড কাঠামোতে ইতিমধ্যে প্রয়োগ করা কার্যকারিতাটি মূলত নকল করছেন। ListViewপুনরুদ্ধার জরিমানা স্ক্রোল অবস্থানে শুধু ভাল তার নিজের উপর ব্যতীত এক সতর্কীকরণ: যেমন @aaronvargas উল্লিখিত সেখানে একটি বাগ রয়েছে AbsListViewযে প্রথম তালিকা আইটেমের জন্য জরিমানা স্ক্রোল অবস্থানে ফিরিয়ে আনতে দেওয়া হবে না। তবুও স্ক্রোল অবস্থান পুনরুদ্ধার করার সেরা উপায় এটি পুনরুদ্ধার করা নয়। অ্যান্ড্রয়েড কাঠামো এটি আপনার জন্য আরও ভাল করবে। আপনি নিম্নলিখিত শর্তগুলি পূরণ করেছেন তা নিশ্চিত করুন:

  • নিশ্চিত করুন যে আপনি setSaveEnabled(false)পদ্ধতিটি কল করেননি android:saveEnabled="false"এবং এক্সএমএল লেআউট ফাইলের তালিকার জন্য অ্যাট্রিবিউট সেট করেন নি
  • জন্য ExpandableListViewওভাররাইড 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এখানে উদাহরণস্বরূপ প্রকল্পটি দেখায় ListViewএবং ExpandableListViewতাদের সূক্ষ্ম স্ক্রোল অবস্থানগুলি পুনরুদ্ধার করুন যেখানে তাদের স্ক্রোল অবস্থানগুলি স্পষ্টভাবে সংরক্ষণ করা হয়নি / পুনঃস্থাপন করা হয়েছে। আরও কিছু অ্যাপ্লিকেশনটিতে অস্থায়ী স্যুইচিং, ডাবল স্ক্রিন ঘোরানো এবং পরীক্ষার অ্যাপ্লিকেশনটিতে ফিরে যাওয়ার জটিল জটিল পরিস্থিতিতেও দুর্দান্ত স্ক্রোল অবস্থানটি পুরোপুরি পুনরুদ্ধার করা হয়েছে। দয়া করে মনে রাখবেন, আপনি যদি স্পষ্টভাবে অ্যাপ্লিকেশনটি থেকে বেরিয়ে আসছেন (পিছনে বোতাম টিপে) স্ক্রোলের অবস্থানটি সংরক্ষণ করা হবে না (পাশাপাশি অন্যান্য সমস্ত দর্শন তাদের রাজ্য সংরক্ষণ করবে না)। https://github.com/voromto/RestoreScrollPosition/releases


0

লিডএ্যাকটিভিটি থেকে প্রাপ্ত এমন ক্রিয়াকলাপের জন্য যা লোডারম্যানাজার.লুডারক্যালব্যাকসকে সিম্পলসার্সার অ্যাডাপ্টার ব্যবহার করে এটি অনারেটে অবস্থান পুনরুদ্ধার করতে কাজ করে না (), কারণ কার্যকলাপটি প্রায় সর্বদা পুনরায় চালু হয়েছিল এবং বিশদ বিবরণটি বন্ধ হয়ে গেলে অ্যাডাপ্টারটি পুনরায় লোড করা হয়েছিল। কৌতুকটি ছিল অনলাইনে ফিনিশড () এর অবস্থান পুনরুদ্ধার করার:

অনলিস্টিমেটিক্লিক ():

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

অন ​​লোডফিনিশড ():

// restore the selected item which was saved on item click
// when details are closed and list is shown again
getListView().setSelectionFromTop(index, top);

অনব্যাকপ্রেসড ():

// Show the top item at next start of the app
index = 0;
top = 0;

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

0

আমার উত্তর ফায়ারবেসের জন্য এবং পজিশন 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) {
        }
    });

এবং রূপান্তর দেখুন

অবস্থান 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;
}
}

আমি ব্যবহারকারীকে বিরক্ত না করে এই কাজটি অস্থায়ীভাবে দেখেছি, আমি আশা করি এটি আপনার পক্ষে কাজ করে


0

নীচের কোডটি ব্যবহার করুন:

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

0

আমি ফায়ারব্যাসলিস্টএডাপ্টার ব্যবহার করছি এবং কাজের কোনও সমাধান পেতে পারি নি। আমি এই কাজ শেষ। আমি অনুমান করছি যে আরও মার্জিত উপায় আছে তবে এটি একটি সম্পূর্ণ এবং কার্যক্ষম সমাধান।

অনক্রিট করার আগে:

private int reset;
private int top;
private int index;

ফায়ারবেসলিস্টএডাপ্টারের অভ্যন্তরে:

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

যেহেতু ফায়ারব্যাসেরেক্লারএডাপ্টারের জন্য আমারও এটি সমাধান করতে হয়েছিল আমি তার জন্য এখানে সমাধানটি পোস্ট করছি:

অনক্রিট করার আগে:

private int reset;
private int top;
private int index;

ফায়ারবেসআরসিক্রারএডাপ্টারের অভ্যন্তরে:

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

0

রায়ান নিউজমের দুর্দান্ত উত্তরটি স্পষ্ট করার জন্য এবং এটি টুকরো টুকরো করার জন্য এবং সাধারণ ক্ষেত্রে যে আমরা "মাস্টার" লিস্টভিউ খণ্ড থেকে একটি "বিশদ" খণ্ডে নেভিগেট করতে চাই এবং তারপরে "মাস্টার" -এ ফিরে যেতে চাই

    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
    }

এখানে "যাদু" হ'ল আমরা যখন বিবরণ খণ্ড থেকে তালিকাভিউ খণ্ডে ফিরে যাই, দৃশ্যটি পুনরায় তৈরি করা হয় না, আমরা তালিকাভিউয়ের অ্যাডাপ্টারটি সেট করি না, সুতরাং সবকিছু যেমন রেখেছিল তেমনি থাকে!

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.