2013-11-28 5 views
9

내 Listview에 문제가 있습니다. 모든 ListView의 항목에 카운트 다운 타이머를 설정하고 싶습니다.이 문제에 대한 해결책을 찾지 못했지만 제대로 작동하지 않습니다. 문제는 ListView가 뷰를 재사용한다는 것이고, 나는 항상 잘못된 아이템 타임을 얻는다. 내 견해로는 태그를 사용하지만 여전히 작동하지 않습니다. 내가 실수 한 부분을 이해할 수 없습니다. 제발 도와주세요. 고마워.ListView 및 카운트 다운 타이머가있는 항목

여기 내 문제를 보여주는 사진 : pic1 방금 활동을 시작했습니다. startActivity

난 그냥 아래로 스크롤 한 PIC2 최대 여기

listWithError

그리고 내 코드 (전체 클래스) :

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

I so 제 경우에는 이것을 다르게 사용했습니다. getView() 안에 타이머 처리기를 설정하는 대신 getView()이 호출 될 때마다 현재 시간과 원하는 시간 사이의 시간차를 TextView으로 설정합니다. 그래서 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); 

그런 다음 목록보기의 어댑터에 매 1 분마다 notifyDatasetChanged()를 호출하는 활동에 처리기를 만들

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

그리고 onResume()에 다시 시작 :

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

그리고 그게 전부입니다. :)

희망이 있습니다.

+0

내 코드를 볼 때 타이머 자체가 없었습니다. 핸들러를 사용하여 notifyDataSetChanged()를 호출 한 핸들러를 사용하여 listview가 자식에게 잘못된 타이머를 설정 한 이유를 알지 못했습니다. Answer – whizzzkey

+0

@whizzzkey getView() 내부에 타이머 핸들러가 있습니다. 그러지 마. 그것이 효과가 있는지보기 위해 제안한 것처럼 해보십시오. –

+0

답변을 업데이트했습니다. 지금 그것이 더 명확한 지보십시오. –

1

recyclerview를 사용할 수 있습니다. 여기에서 다운로드 소스 코드()

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> 
,536,913,632 10

사용자 정의 어댑터 :

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



} 

감사합니다!