2013-11-28 23 views
9

Tôi gặp vấn đề với Listview, tôi muốn đặt đồng hồ đếm ngược cho tất cả các mục của ListView và tôi đã có giải pháp cho điều này nhưng nó không hoạt động chính xác. Vấn đề là ListView reuses (tái chế) một lượt xem, và tôi luôn luôn nhận được một mục thời gian sai. Tôi sử dụng một thẻ cho xem của tôi, nhưng nó vẫn không hoạt động, tôi không thể hiểu nơi tôi đã làm sai, xin vui lòng giúp tôi. cám ơn.ListView và các mục có đồng hồ đếm ngược

Vì vậy, đây là một hình ảnh hiển thị sự cố của tôi: pic1 Tôi vừa mới bắt đầu Hoạt động ở đâu; startActivity

pic2 đâu tôi vừa cuộn xuống và lên

listWithError

Và đây mã của tôi (cả lớp):

CẬP NHẬT

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

}

Trả lời

10

Tôi cũng vậy lved này khác nhau trong trường hợp của tôi. Thay vì có bộ xử lý hẹn giờ được đặt trong số getView(), tôi chỉ đặt chênh lệch thời gian giữa thời gian hiện tại và thời gian mong muốn của bạn thành TextView mỗi lần gọi getView(). Vì vậy, di chuyển mã này của anh trở lại bên trong getView():

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

Sau đó tạo một handler trong hoạt động để gọi notifyDatasetChanged() mỗi một phút trên adapter của listview:

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

tôi dừng xử lý này trên onPause():

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

Và tôi bắt đầu lại trên onResume():

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

Và đó là nó. :)

Hy vọng điều đó sẽ hữu ích.

+0

Tôi không có bộ đếm thời gian, như bạn thấy mã của tôi, tôi sử dụng trình xử lý để gọi notificationDataSetChanged() giống như bạn, tôi không hiểu lý do tại sao listview đặt bộ hẹn giờ sai cho con của nó, bất kể nó là gì answer – whizzzkey

+0

@whizzzkey Bạn đang xử lý bộ đếm thời gian bên trong 'getView()'. Đừng làm thế. Hãy thử làm điều đó như tôi đề nghị để xem nó hoạt động. –

+0

Tôi đã cập nhật câu trả lời của mình. Xem nếu nó là rõ ràng hơn bây giờ. –

1

Bạn có thể sử dụng recyclerview. code Tải về mã nguồn từ đây()

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> 

Tuỳ chỉnh Adaptor:

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



} 

Cảm ơn!

Các vấn đề liên quan