1.之前没怎么在ListView的Item条目中嵌套Seekbar, 突然有朋友遇到这样的情况,于是花点时间解决下
网上找的一些blog基本没什么用,可能是我的手法不对,本篇实测有效
解决问题
seekbar在listview的item中时,点击定时加载进度时,滑动listview,seekbar复用的部分也会被定时器控制进行进度加载
listview的常规用法,
设置适配器
适配器中四个方法 最重要的getView
convertView复用Item条目
自定义ViewHolder保存控件 避免频繁查找控件
这里贴一下getView的代码
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(mContext, R.layout.item_seekbar, null);
holder.mTextView = convertView.findViewById(R.id.tv_play);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText("播放" + position);
return convertView;
}
class ViewHolder {
private TextView mTextView;
}
}
上面是 listview的convertView复用流程
比如说一个界面最多需要 6个条目覆盖慢,如果使用了convertView复用,那么在下滑时第7个条目刚刚出现,但第一个条目完全消失时,getView 会获取第一个的ItemView 作为convertView , 我们又convertView带了当前也就是第7个条目展示的Item
所以第7个的View就是第1个
listview中每个条目的区别不在于控件 而在于数据 数据通过position进行区分,我们只要将position绑定到convertView 实际上就可以了 ,看了几篇网文,可能是拷错了
每次getView 表示初始化一个ItemView 我们都需要对其绑定position,可以绑定到某个控件 view.setTag
也可以绑定到ViewHolder
但需要注意的是 不管是否复用View 都需要对于position进行绑定
我这里会在下面初始化的定时器的回调中对于当前 view中获取的position和 点击播放的position进行比较,来判断当前的条目是否为复用条目,而不是原本点击的条目
还是贴出关键代码 getView
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(mContext, R.layout.item_seekbar, null);
holder.mTextView = convertView.findViewById(R.id.tv_play);
holder.mSeekBar = convertView.findViewById(R.id.tv_seekbar);
holder.mTextView.setTag(position);
holder.mSeekBar.setTag(position);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.mTextView.setTag(position);
holder.mSeekBar.setTag(position);
}
holder.mTextView.setText("播放" + position);
holder.mSeekBar.setMax(100);
holder.mSeekBar.setProgress(0);
holder.mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
choosePosition =position;
timer = new Timer();
final Handler handler = new Handler();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
currentPlayProgress++;
if ((int)holder.mTextView.getTag() == choosePosition) {
if (currentPlayProgress > 100) {
currentPlayProgress = 0;
holder.mSeekBar.setProgress(currentPlayProgress);
timer.cancel();
} else {
holder.mSeekBar.setProgress(currentPlayProgress);
}
}
}
});
}
}, 100, 1000);
}
});
return convertView;
}
class ViewHolder {
private SeekBar mSeekBar;
private TextView mTextView;
}
实际上 上面的gif图还有一点点小问题,就是 从下往上滑动时,第一个条目重新出现 一开始显示进度0
这个在getView 初始化数据时做一点小变动,判断当前是否为进行进度加载中的条目,做进度更新就可以了
holder.mSeekBar.setMax(100);
if (choosePosition == position) {
holder.mSeekBar.setProgress(currentPlayProgress);
} else {
holder.mSeekBar.setProgress(0);
}
下面贴一下全部代码
adapter
package com.example.caixingcun.seekbarlistcontroldemo;
import android.content.Context;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.SeekBar;
import android.widget.TextView;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by cxc on 2018/3/22.
*/
public class SeekBarAdapter extends BaseAdapter {
private Context mContext;
private Timer timer;
private int currentPlayProgress = 0;
private int choosePosition = -1;
public SeekBarAdapter(Context context) {
mContext = context;
}
@Override
public int getCount() {
return 30;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = View.inflate(mContext, R.layout.item_seekbar, null);
holder.mTextView = convertView.findViewById(R.id.tv_play);
holder.mSeekBar = convertView.findViewById(R.id.tv_seekbar);
holder.mTextView.setTag(position);
holder.mSeekBar.setTag(position);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.mTextView.setTag(position);
holder.mSeekBar.setTag(position);
}
holder.mTextView.setText("播放" + position);
holder.mSeekBar.setMax(100);
if (choosePosition == position) {
holder.mSeekBar.setProgress(currentPlayProgress);
} else {
holder.mSeekBar.setProgress(0);
}
holder.mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
choosePosition = position;
timer = new Timer();
final Handler handler = new Handler();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
currentPlayProgress++;
if ((int) holder.mTextView.getTag() == choosePosition) {
if (currentPlayProgress > 100) {
currentPlayProgress = 0;
holder.mSeekBar.setProgress(currentPlayProgress);
timer.cancel();
} else {
holder.mSeekBar.setProgress(currentPlayProgress);
}
}
}
});
}
}, 100, 1000);
}
});
return convertView;
}
class ViewHolder {
private SeekBar mSeekBar;
private TextView mTextView;
}
}
MainActivity
setContentView(R.layout.activity_main);
mListView = findViewById(R.id.lv);
mListView.setAdapter(new SeekBarAdapter(this));
item_seekbar.xml
靠这篇文章解决问题的,帮忙点个赞! 打字不易