2013-11-28 17 views
9

मुझे अपने लिस्टव्यू के साथ कोई समस्या है, मैं सभी ListView के आइटम्स में उलटी गिनती टाइमर सेट करना चाहता हूं, और मैंने पहले से ही इसके लिए एक समाधान किया है, लेकिन यह सही ढंग से काम नहीं कर रहा है। समस्या यह है कि ListView एक विचार (रीसाइक्लिंग) का पुन: उपयोग करता है, और मुझे हमेशा एक गलत आइटम समय मिलता है। मैं अपने विचार के लिए एक टैग का उपयोग करता हूं, लेकिन यह अभी भी काम नहीं करता है, मैं समझ नहीं पा रहा हूं कि मैंने गलती कहाँ की है, कृपया मेरी मदद करें। धन्यवाद।सूची दृश्य और उलटी गिनती टाइमर के साथ आइटम

तो यहां एक चित्र जो मेरी समस्या दिखाता है: pic1 जहां मैंने अभी एक गतिविधि शुरू की है; startActivity

pic2 कहाँ मैं सिर्फ नीचे स्क्रॉल किया गया है और ऊपर

listWithError

और यहाँ मेरे कोड (पूरी कक्षा):

UPDATED

public class PromoListActivity extends SherlockActivity { 
private ListView mPromoList; 
private PromoListAdapter mAdapter; 
private ViewFlipper mFlipper; 
private Button mBtnRepeat; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.fragment_news_list); 
    getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
    setTitle("Сохранённые акции"); 
    mFlipper = (ViewFlipper) findViewById(R.id.flipper); 
    mPromoList = (ListView) findViewById(R.id.newsList); 
    mBtnRepeat = (Button) findViewById(R.id.btnRepeat); 

    //--> 
    final Handler timerHandler = new Handler(); 
    Runnable timerRunnable = new Runnable() { 
     @Override 
     public void run() { 
      mAdapter.notifyDataSetChanged(); 
      timerHandler.postDelayed(this, 1000); // run every minute 
     } 
    }; 
    //<-- 


    mBtnRepeat.setOnClickListener(new OnClickListener() { 

     @Override 
     public void onClick(View arg0) { 
      mFlipper.setDisplayedChild(0); 
      getDummyData(); 
     } 
    }); 
    mPromoList.setOnItemClickListener(new OnItemClickListener() { 

     @Override 
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { 
      startActivity(new Intent(PromoListActivity.this, PromoActivityDetails.class)); 

     } 
    }); 
    getDummyData(); 
} 

private class PromoListAdapter extends BaseAdapter { 
    private ArrayList<PromoAction> mItems = new ArrayList<PromoAction>(); 
    private LayoutInflater layoutInflater; 

    private PromoListAdapter(Context context, ArrayList<PromoAction> mItems) { 
     layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     this.mItems = mItems; 
    } 

    public int getCount() { 
     return mItems.size(); 
    } 

    public PromoAction getItem(int position) { 
     return mItems.get(position); 
    } 

    public long getItemId(int position) { 
     return position; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     ViewItem viewItem; 
     PromoAction promoAction = getItem(position); 
     if (convertView == null) { 
      viewItem = new ViewItem(); 
      convertView = layoutInflater.inflate(R.layout.listviewitem_action, null); 
      viewItem.name = (TextView) convertView.findViewById(R.id.promoAction_name); 
      viewItem.desc = (TextView) convertView.findViewById(R.id.promoAction_desc); 
      viewItem.timer = (TextView) convertView.findViewById(R.id.promoAction_timer); 
      viewItem.timer.setTag(position); 
      convertView.setTag(viewItem); 
     } else { 
      viewItem = (ViewItem) convertView.getTag(); 
     } 
     setTime(promoAction,viewItem.timer,viewItem.timer.getTag().toString()); 
     viewItem.name.setText(promoAction.name); 
     viewItem.desc.setText(promoAction.descr); 
     return convertView; 
    } 

    private void setTime(final PromoAction promoAction, final TextView tv, final String tag) { 
     if (tv.getTag().toString().equals(tag)) { 
      long outputTime = Math.abs(promoAction.timer_end 
        - System.currentTimeMillis()); 
      Date date = new java.util.Date(outputTime); 
      String result = new SimpleDateFormat("hh:mm:ss").format(date); 
      tv.setText(result); 
     } 
    } 

    public class ViewItem { 
     TextView name; 
     TextView desc; 
     TextView timer; 
    } 
} 

private void getDummyData() { 
    ArrayList<PromoAction> list = new ArrayList<PromoAction>(); 
    for (int i = 1; i < 10; i++) { 
     PromoAction action = new PromoAction(); 
     action.name = "Lorem ipsum dolor sit amet"; 
     action.descr = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "; 
     switch (i) { 
     case 1: { 
      action.timer_start = 1385971000; 
      action.timer_end = 1386104000; 
     } 
     case 2: { 
      action.timer_start = 1385889000; 
      action.timer_end = 1385812550; 
      break; 
     } 
     case 3: { 
      action.timer_start = 1385884200; 
      action.timer_end = 1385912100; 
      break; 
     } 
     default: { 
      action.timer_start = 1385856000; 
      action.timer_end = 1385892000; 
      break; 
     } 
     } 
     list.add(action); 

    } 
    mAdapter = new PromoListAdapter(PromoListActivity.this, list); 
    mPromoList.setAdapter(mAdapter); 
    mFlipper.setDisplayedChild(1); 
} 

}

उत्तर

10

मैं ऐसा करता हूं मेरे मामले में यह अलग-अलग लुप्त हो गया। अपने getView() के अंदर टाइमर हैंडलर सेट करने के बजाय, मैंने वर्तमान समय और 0 वांपर 0 वांपर वांछित समय के बीच का समय अंतर निर्धारित किया है। तो getView() अंदर वापस आपके इस कोड के लिए कदम:

Handler timerHandler = new Handler(); 
Runnable timerRunnable = new Runnable() { 
    @Override 
    public void run() { 
     myAdapter.notifyDataSetChanged(); 
     timerHandler.postDelayed(this, 60000); //run every minute 
    } 
}; 

मैं onPause() पर इस हैंडलर रोक:

long outputTime = Math.abs(promoAction.timer_end 
        - System.currentTimeMillis()); 
Date date = new java.util.Date(outputTime); 
String result = new SimpleDateFormat("hh:mm:ss").format(date); 
tv.setText(result); 

फिर notifyDatasetChanged() सूचीदृश्य के एडाप्टर पर हर एक मिनट के कॉल करने के लिए गतिविधि में एक हैंडलर बनाने

@Override 
protected void onPause() { 
    timerHandler.removeCallbacks(timerRunnable); 
    super.onPause(); 
} 

और मैं onResume() पर इसे फिर से शुरू:

@Override 
protected void onResume() { 
    timerHandler.postDelayed(timerRunnable, 500); 
    super.onResume(); 
} 

और यही वह है। :)

उम्मीद है कि यह मदद करता है।

+0

मैं एक टाइमर ही नहीं था, जैसा कि आप मेरी कोड देखते हैं, मैं हैंडलर का उपयोग notifyDataSetChanged() कॉल करने के लिए ठीक वैसे ही जैसे, मैं हो क्यों सूचीदृश्य अपने बच्चे को, जो कुछ भी यह करने के लिए धन्यवाद था गलत टाइमर सेट नहीं किया अपने उत्तर – whizzzkey

+0

@whizzzkey आप 'getView() 'के अंदर टाइमर हैंडलर रखते हैं। ऐसा मत करो। ऐसा करने का प्रयास करें जैसे मैंने यह देखने का सुझाव दिया कि यह काम करता है या नहीं। –

+0

मैंने अपना जवाब अपडेट किया। देखें कि यह अब स्पष्ट है या नहीं। –

1

आप पुनर्चक्रण का उपयोग कर सकते हैं। यहां से डाउनलोड स्रोत कोड()

activity_main.xml

<RelativeLayout android:layout_width="match_parent" 
android:layout_height="match_parent" 
xmlns:android="http://schemas.android.com/apk/res/android"> 

<android.support.v7.widget.RecyclerView 
android:id="@+id/recycler_view" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:scrollbars="vertical" /> 

</RelativeLayout> 

MainActivity.java

package com.androidsolutionworld.multipletimer; 

import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.support.v7.widget.LinearLayoutManager; 
import android.support.v7.widget.RecyclerView; 
import android.widget.LinearLayout; 

import java.util.ArrayList; 

public class MainActivity extends AppCompatActivity { 
    private RecyclerView recyclerView; 
    private ArrayList al_data = new ArrayList<>(); 
    private Adapter obj_adapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     recyclerView = (RecyclerView)findViewById(R.id.recycler_view); 
     al_data.add("1234"); 
     al_data.add("1257"); 
     al_data.add("100"); 
     al_data.add("1547"); 
     al_data.add("200"); 
     al_data.add("500"); 
     al_data.add("2000"); 
     al_data.add("1000"); 

     obj_adapter = new Adapter(al_data); 
     LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext(),LinearLayoutManager.VERTICAL,false); 
     recyclerView.setLayoutManager(layoutManager); 
     recyclerView.setAdapter(obj_adapter); 
    } 
} 

adapter_layout.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:textSize="15dp" 
     android:padding="10dp" 
     android:id="@+id/tv_timer"/> 

</LinearLayout> 

कस्टम एडाप्टर:

package com.androidsolutionworld.multipletimer; 


import android.os.CountDownTimer; 
import android.support.v7.widget.RecyclerView; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

import java.util.ArrayList; 

public class Adapter extends RecyclerView.Adapter{ 

    private ArrayList al_data; 

    public class MyViewHolder extends RecyclerView.ViewHolder{ 
     public TextView tv_timer; 
     CountDownTimer timer; 

     public MyViewHolder (View view){ 
      super(view); 
      tv_timer = (TextView)view.findViewById(R.id.tv_timer); 

     } 


    } 

    public Adapter(ArrayList al_data) { 
     this.al_data = al_data; 
    } 

    @Override 
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout,parent,false); 


     return new MyViewHolder(view); 
    } 

    @Override 
    public void onBindViewHolder(final MyViewHolder holder, int position) { 

     holder.tv_timer.setText(al_data.get(position)); 

     if (holder.timer != null) { 
      holder.timer.cancel(); 
     } 
     long timer = Long.parseLong(al_data.get(position)); 

     timer = timer*1000; 

     holder.timer = new CountDownTimer(timer, 1000) { 
      public void onTick(long millisUntilFinished) { 
       holder.tv_timer.setText("" + millisUntilFinished/1000 + " Sec"); 
      } 

      public void onFinish() { 
       holder.tv_timer.setText("00:00:00"); 
      } 
     }.start(); 


    } 

    @Override 
    public int getItemCount() { 
     return al_data.size(); 
    } 



} 

धन्यवाद!

संबंधित मुद्दे