Android ListView Rows का आदी या निष्कासन कैसे करें


212

IOS में, UITableView पंक्तियों को जोड़ने और हटाने का प्रयास करने के लिए एक बहुत ही आसान और शक्तिशाली सुविधा है, यहां एक यूट्यूब वीडियो से एक क्लिप डिफ़ॉल्ट एनीमेशन दिखा रहा है। ध्यान दें कि आसपास की पंक्तियाँ हटाए गए पंक्ति पर कैसे गिरती हैं। यह एनीमेशन उपयोगकर्ताओं को इस बात पर नज़र रखने में मदद करता है कि किसी सूची में क्या बदला और कहाँ सूची में वे उस समय देख रहे थे जब डेटा बदल गया था।

जब से मैं एंड्रॉइड पर विकास कर रहा हूं, मुझे एक टेबल व्यू में व्यक्तिगत पंक्तियों को चेतन करने के लिए कोई समान सुविधा नहीं मिली है । notifyDataSetChanged()मेरे एडप्टर पर कॉल करने से लिस्ट व्यू तुरंत नई जानकारी के साथ अपनी सामग्री को अपडेट करता है। जब डेटा में बदलाव होता है, तो मैं एक नई पंक्ति का एक सरल एनीमेशन दिखाना चाहता हूं या उसमें खिसकना चाहता हूं, लेकिन मुझे ऐसा करने का कोई दस्तावेज नहीं मिला है। ऐसा लगता है कि LayoutAnimationController को काम करने के लिए एक कुंजी मिल सकती है, लेकिन जब मैं अपने ListView ( ApiDemo के LayoutAnimation2 के समान ) पर एक LayoutAnimationController सेट करता हूं और सूची प्रदर्शित होने के बाद अपने एडॉप्टर से तत्वों को हटाता है, तो तत्व तुरंत अनुपलब्ध होने के बजाय गायब हो जाते हैं। ।

मैंने किसी आइटम को हटाए जाने के बाद निम्नलिखित चीजों को भी आज़माया है:

@Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
    Animation animation = new ScaleAnimation(1, 1, 1, 0);
    animation.setDuration(100);
    getListView().getChildAt(position).startAnimation(animation);
    l.postDelayed(new Runnable() {
        public void run() {
            mStringList.remove(position);
            mAdapter.notifyDataSetChanged();
        }
    }, 100);
}

हालाँकि, एनिमेटेड पंक्ति के आस-पास की पंक्तियाँ तब तक स्थिति को स्थानांतरित नहीं करती हैं जब तक कि वे अपने नए पदों पर नहीं जातीं जब उन्हें notifyDataSetChanged()बुलाया जाता है। ऐसा लगता है कि एक बार जब इसके तत्व रख दिए गए हैं तो ListView अपने लेआउट को अपडेट नहीं करता है।

लिस्ट व्यू के अपने कार्यान्वयन / कांटे को लिखने के दौरान मेरे दिमाग को पार कर गया है, यह कुछ ऐसा लगता है जो इतना मुश्किल नहीं होना चाहिए।

धन्यवाद!


किसी को इस का जवाब मिल गया? कृपया shareee
AndroidGecko

@ एलेक्स: क्या आपने उस यूट्यूब वीडियो (जैसे iphone) पर एनीमेशन किया है, अगर आपके पास एंड्रॉइड के लिए कोई डेमो या लिंक है तो कृपया मुझे दें, मैंने xml फ़ाइल में animateLayoutChanges का उपयोग करने की कोशिश की है, लेकिन यह बिल्कुल iphone की तरह नहीं है
जयेश

@ जयेश, दुर्भाग्य से मैं अब एंड्रॉइड डेवलपमेंट पर काम नहीं करता हूं। मैंने इस सवाल के किसी भी उत्तर का परीक्षण नहीं किया है जो 2012 के आसपास लिखा गया था।
एलेक्स प्रेट्ज़लाव

जवाबों:


124
Animation anim = AnimationUtils.loadAnimation(
                     GoTransitApp.this, android.R.anim.slide_out_right
                 );
anim.setDuration(500);
listView.getChildAt(index).startAnimation(anim );

new Handler().postDelayed(new Runnable() {

    public void run() {

        FavouritesManager.getInstance().remove(
            FavouritesManager.getInstance().getTripManagerAtIndex(index)
        );
        populateList();
        adapter.notifyDataSetChanged();

    }

}, anim.getDuration());

ऊपर से नीचे एनीमेशन उपयोग के लिए:

<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromYDelta="20%p" android:toYDelta="-20"
            android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

70
anim.setAnimationListener(new AnimationListener() { ... })एक हैंडलर का उपयोग करने के बजाय इसका उपयोग करना बेहतर है
ओलेग वासकेविच

1
किस populateList()लिए है
वासिली सोचिंस्की

5
@MrAppleBR कई कारणों से। सबसे पहले, आप एक अनावश्यक नहीं बना रहे हैं Handler। दूसरा, जब एनीमेशन खत्म हो जाता है तो यह बिल्ट-इन कॉलबैक का उपयोग करके कोड को कम जटिल बना देता है। तीसरा, आप यह नहीं जानते कि किस तरह का कार्यान्वयन Handlerऔर Animationप्रत्येक प्लेटफॉर्म पर काम करेगा; यह संभव हो सकता है कि एनीमेशन समाप्त होने से पहले आपका विलंबित रननेबल हो।
ओलेग वासकेविच

7
"हालांकि, एनिमेटेड पंक्ति के आसपास की पंक्तियाँ तब तक स्थिति को स्थानांतरित नहीं करती हैं जब तक कि वे अपने नए पदों पर नहीं पहुंचते हैं जब InformDataSetChanged () कहा जाता है।" यह समस्या अभी भी आपके समाधान में बनी हुई है।
बोरिस रुसेव

5
FavouritesManager वर्ग और populateList () विधि क्या है ??
जयेश

14

1
मुझे लगता है कि यह एक सरल तरीका है जब आपको एक सरल एनीमेशन की आवश्यकता होती है, लेकिन आप RecyclerView.setItemAnimator () विधि का उपयोग करके एनीमेशन को कस्टम भी कर सकते हैं।
१-१५ बजे qatz

2
अंतिम चरण मेरे पास गुम लिंक है। स्थिर आईडी है। धन्यवाद!
अमीर उवल

यह एक महान नमूना परियोजना है जो एपीआई को अच्छी तरह से प्रदर्शित करता है।
मिस्टर-आईडीई

9

Google समाधान पर एक नज़र डालें। यहाँ केवल एक विलोपन विधि है।

ListViewRemovalAnimation प्रोजेक्ट कोड और वीडियो प्रदर्शन

इसे Android 4.1+ (API 16) की आवश्यकता है। लेकिन हमारे पास 2014 है।


2

चूंकि ListViewsमैं अत्यधिक अनुकूलित हूं, मुझे लगता है कि यह संभव नहीं है। क्या आपने कोड द्वारा अपनी "सूची दृश्य" बनाने की कोशिश की है (यानी xml से अपनी पंक्तियों को फुलाकर और उन्हें जोड़कर LinearLayout) और उन्हें चेतन करें?


6
यह सिर्फ एनिमेशन जोड़ने के लिए सूची को फिर से लागू करने के लिए कोई मतलब नहीं है।
मैकरस

मैं निश्चित रूप से सिर्फ एक का उपयोग कर सकता है LinearLayout, हालांकि बहुत बड़े डेटासेट LinearLayoutके प्रदर्शन के साथ घृणा हो जाएगी। ListViewव्यू रिसाइक्लिंग के आसपास बहुत सारी स्मार्ट ऑप्टिमाइज़ेशन हैं जो इसे बड़े डेटा सेट को संभालने की अनुमति देती हैं (iOS के यूआईटेबल व्यू में समान ऑप्टिमाइज़ेशन हैं)। अपना स्वयं का दृश्य लिखने वाला पुन: लागू करने की सूची के अंतर्गत आता है ListView :(
एलेक्स Pretzlav

मुझे पता है कि यह समझ में नहीं आता है - लेकिन अगर आप सिर्फ कुछ पंक्तियों के साथ काम करते हैं तो / आउट एनिमेशन में अच्छा होने का लाभ कोशिश के लायक हो सकता है।
व्हेल

2

क्या आपने स्वीप को सही माना है? आप सूची आइटम के शीर्ष पर एक उत्तरोत्तर बड़ा सफेद पट्टी खींचने जैसा कुछ कर सकते हैं, फिर इसे सूची से हटा दें। अन्य कोशिकाओं को अभी भी जगह में झटका होगा, लेकिन यह कुछ नहीं से बेहतर होगा।



2

मैंने सूची दृश्य में हेरफेर किए बिना इसे करने का एक और तरीका हैक किया। दुर्भाग्य से, नियमित रूप से एंड्रॉइड एनिमेशन पंक्ति की सामग्री में हेरफेर करते हैं, लेकिन वास्तव में दृश्य को सिकोड़ते हुए अप्रभावी हैं। तो, पहले इस हैंडलर पर विचार करें:

private Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
    Bundle bundle = message.getData();

    View view = listView.getChildAt(bundle.getInt("viewPosition") - 
        listView.getFirstVisiblePosition());

    int heightToSet;
    if(!bundle.containsKey("viewHeight")) {
        Rect rect = new Rect();
        view.getDrawingRect(rect);
        heightToSet = rect.height() - 1;
    } else {
        heightToSet = bundle.getInt("viewHeight");
    }

    setViewHeight(view, heightToSet);

    if(heightToSet == 1)
        return;

    Message nextMessage = obtainMessage();
    bundle.putInt("viewHeight", (heightToSet - 5 > 0) ? heightToSet - 5 : 1);
    nextMessage.setData(bundle);
    sendMessage(nextMessage);
}

इस संग्रह को अपने सूची एडाप्टर में जोड़ें:

private Collection<Integer> disabledViews = new ArrayList<Integer>();

और जोड़

public boolean isEnabled(int position) {
   return !disabledViews.contains(position);
}

अगला, जहाँ भी यह है कि आप एक पंक्ति को छुपाना चाहते हैं, इसे जोड़ें:

Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt("viewPosition", listView.getPositionForView(view));
message.setData(bundle);
handler.sendMessage(message);    
disabledViews.add(listView.getPositionForView(view));

बस! आप एक बार में ऊंचाई को कम करने वाले पिक्सेल की संख्या को बदलकर एनीमेशन की गति को बदल सकते हैं। वास्तविक परिष्कृत नहीं है, लेकिन यह काम करता है!


2

ListView में नई पंक्ति सम्मिलित करने के बाद, मैं सिर्फ ListView को नई स्थिति पर स्क्रॉल करता हूं।

ListView.smoothScrollToPosition(position);

1

मैंने इसे आज़माया नहीं है, लेकिन ऐसा लग रहा है कि चेतनआउटआउट्स को वह करना चाहिए जो आप खोज रहे हैं। मैं इसे ImageSwitcher वर्ग में देखता हूं, मुझे लगता है कि यह ViewSwitcher वर्ग में भी है?


हे धन्यवाद, मैं उस पर गौर करूंगा। दुर्भाग्य से ऐसा लगता है कि चेतन लयआउटचेंज एपीआई स्तर 11 उर्फ ​​हनीकॉम्ब उर्फ ​​के रूप में नया है, यह किसी भी-फोन पर अभी तक उपयोग नहीं कर सकता है :(
एलेक्स प्रिट्ज़लव

1

चूंकि एंड्रॉइड ओपन सोर्स है, इसलिए आपको वास्तव में ListView के अनुकूलन को फिर से लागू करने की आवश्यकता नहीं है। आप ListView के कोड को पकड़ सकते हैं और एनीमेशन में हैक करने का एक तरीका खोजने की कोशिश कर सकते हैं, आप एंड्रॉइड बग ट्रैकर में एक सुविधा अनुरोध भी खोल सकते हैं (और यदि आपने इसे लागू करने का फैसला किया है, तो एक पैच योगदान करना न भूलें। )।

FYI करें, सूची दृश्य स्रोत कोड यहाँ है


1
यह तरीका नहीं है कि इस तरह के बदलावों को लागू किया जाए। कुछ भी करने से पहले, आपके पास एओएसपी प्रोजेक्ट बिल्डिंग होनी चाहिए - जो कि विचारों को सूचीबद्ध करने के लिए एनीमेशन को जोड़ने के लिए काफी भारी हाथ है। कृपया विभिन्न खुले स्रोत पुस्तकालयों में कार्यान्वयन को देखें।
OrhanC1

1

यहाँ स्रोत कोड है है कि आप पंक्तियों को हटा दें और उन्हें फिर से व्यवस्थित करें।

एक डेमो APK फ़ाइल भी उपलब्ध है। Google के जीमेल ऐप की तर्ज पर डिलीट पंक्तियों को अधिक किया जाता है जो शीर्ष दृश्य को स्वाइप करने के बाद एक निचले दृश्य को प्रकट करता है। नीचे के दृश्य में एक पूर्ववत् बटन या आप जो चाहें कर सकते हैं।


1

जैसा कि मैंने अपनी साइट में अपने दृष्टिकोण की व्याख्या की थी मैंने लिंक साझा किया था। वैसे भी विचार बिटकॉइनिंग से बिटमैप बना रहा है। दो बिटमैप और चलती प्रभाव बनाने के लिए कम बिटमैप को चेतन करें।

कृपया निम्नलिखित कोड देखें:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        public void onItemClick(AdapterView<?> parent, View rowView, int positon, long id)
        {
            listView.setDrawingCacheEnabled(true);
            //listView.buildDrawingCache(true);
            bitmap = listView.getDrawingCache();
            myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), rowView.getBottom());
            myBitmap2 = Bitmap.createBitmap(bitmap, 0, rowView.getBottom(), bitmap.getWidth(), bitmap.getHeight() - myBitmap1.getHeight());
            listView.setDrawingCacheEnabled(false);
            imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1));
            imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
            imgView1.setVisibility(View.VISIBLE);
            imgView2.setVisibility(View.VISIBLE);
            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(0, rowView.getBottom(), 0, 0);
            imgView2.setLayoutParams(lp);
            TranslateAnimation transanim = new TranslateAnimation(0, 0, 0, -rowView.getHeight());
            transanim.setDuration(400);
            transanim.setAnimationListener(new Animation.AnimationListener()
            {
                public void onAnimationStart(Animation animation)
                {
                }

                public void onAnimationRepeat(Animation animation)
                {
                }

                public void onAnimationEnd(Animation animation)
                {
                    imgView1.setVisibility(View.GONE);
                    imgView2.setVisibility(View.GONE);
                }
            });
            array.remove(positon);
            adapter.notifyDataSetChanged();
            imgView2.startAnimation(transanim);
        }
    });

छवियों के साथ समझने के लिए इसे देखें

धन्यवाद।


0

मैंने ऐसा ही कुछ किया है। एक दृष्टिकोण सूची दृश्य के लिए onMeasureजारी करते समय पंक्तियों के भीतर समय के साथ दृश्य की ऊंचाई एनीमेशन समय पर प्रक्षेपित करना है requestLayout()। हाँ यह सीधे listView कोड के अंदर करने के लिए बेहतर हो सकता है, लेकिन यह एक त्वरित समाधान था (जो अच्छा लगा!)


0

बस एक और दृष्टिकोण साझा करना:

पहले सूची दृश्य के Android को सेट करें : चेतन को सत्य के लिए चेतन करें :

<ListView
        android:id="@+id/items_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"/>

फिर मैं वस्तुओं को जोड़ने और विलंब के साथ सूची को अद्यतन करने के लिए एक हैंडलर का उपयोग करता हूं :

Handler mHandler = new Handler();
    //delay in milliseconds
    private int mInitialDelay = 1000;
    private final int DELAY_OFFSET = 1000;


public void addItem(final Integer item) {
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mDataSet.add(item);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.notifyDataSetChanged();
                        }
                    });
                }
            }).start();

        }
    }, mInitialDelay);
    mInitialDelay += DELAY_OFFSET;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.