Sli*_* C. 2 android listview seekbar android-recyclerview
我有一个奇怪的问题.我有一个自定义ListView
用BaseAdapter
.在我的ListView
行布局中,我有几个TextView
s Buttons
,和a SeekBar
.一切都很好,没有任何问题,除了回收.
会发生什么:SeekBar
除了可见之外,所有的都是隐藏的.的SeekBar
是,当看到MediaPlayer
上排播放.那部分也很有效.
但是,当用户向上或向下滚动,并且具有可见的行SeekBar
不在视图中时,它会循环使用,并且SeekBar
也会被回收,并且即使它不可见并且该行未播放(mp)也会不断更新.当用户向后滚动以返回正在播放的视图时,SeekBar
是可见的,但是没有更新,它的位置是0.而是随机SeekBar
更新,但它不可见(我测试的时候所有SeekBar
的都可见所以我知道发生)
当然,我可以完成最愚蠢的解决方案并禁用ListView回收,但这会让用户体验非常糟糕,并且可能会使应用程序耗尽内存,并且使用LargeHeap
是蹩脚的.所以以下方法是不可能的.
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
Run Code Online (Sandbox Code Playgroud)
我的问题:这有什么明显的解决方案吗?如何仅保留一行不被回收?我不会发布代码,直到它真的有必要,代码太大了.相反,我将发布与问题相关的重要部分:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
holder = null;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.item, parent, false);
holder = new Ids(row);
row.setTag(holder);
} else {
holder = (Ids) row.getTag();
}
rowItemClass = (ListViewRow) getItem(position);
if (Globals.isPlaying && Globals.pos == position) {
holder.seekbar.setVisibility(View.VISIBLE);
} else {
holder.seekbar.setVisibility(View.GONE);
}
holder.seekbar.setTag(position);
final Ids finalHolder = holder;
...
OnClickListener{....
Globals.mp.start();
finalHolder.seekbar.setProgress(0);
finalHolder.seekbar.setMax(Globals.mp.getDuration());
..
updateTimeProgressBar = new Runnable() {
@Override
public void run() {
if (Globals.isPlaying) {
finalHolder.seekbar.setProgress(Globals.mp.getCurrentPosition());
int currentPosition = Globals.mp.getCurrentPosition();
handler.postDelayed(this, 100);
}
}
};
handler.postDelayed(updateTimeProgressBar, 100);
finalHolder.seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
handler.removeCallbacks(updateTimeProgressBar);
Globals.mp.seekTo(finalHolder.seekbar.getProgress());
int currentPosition = Globals.mp.getCurrentPosition();
handler.postDelayed(updateTimeProgressBar, 500);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
handler.removeCallbacks(updateTimeProgressBar);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// Intentionally left empty
}
});
}
Run Code Online (Sandbox Code Playgroud)
就是这样.为什么会这样?有没有办法禁用一行回收?更新所有SeekBar
s 是不是一个坏主意,ListView
因为只有1 mp将会播放?性能有多糟糕?
我将概述解决这一问题的最佳方法之一(当然,我认为),同时尊重ListView's
回收利用的能力.
但首先,必须要:
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getItemViewType(int position) {
return position;
}
Run Code Online (Sandbox Code Playgroud)
解:
子类SeekBar
并让它处理所有更新:
定义两个标记此 SeekBar
活动和非活动的方法.
标记SeekBar
活动时,提供当前位置(进度).旁边,张贴的Runnable
,将更新此SeekBar
标记SeekBar
非活动时,只需删除该回调Runnable
并在一天内调用它
在你的内部Adapter
,你需要保持的唯一状态是跟踪当前正在播放的歌曲.您可以通过跟踪您所看到的位置ListView
,或者通过保持ID
当前正在播放的曲目来执行此操作(当然,这仅在您的模型使用ID时才有效).
像这样的东西:
// Define `setActiveAtPosition(int position)` and `setInactive()`
// in your custom SeekBar
if (Globals.isPlaying && Globals.pos == position) {
// Define `setActiveAtPosition(int position)` in your custom SeekBar
holder.seekbar.setActiveAtPosition(Globals.mp.getCurrentPosition());
holder.seekbar.setVisibility(View.VISIBLE);
} else {
holder.seekbar.setInactiveForNow();
holder.seekbar.setVisibility(View.GONE);
}
Run Code Online (Sandbox Code Playgroud)
请求的代码:
自定义Seekbar类实现:
public class SelfUpdatingSeekbar extends SeekBar implements SeekBar.OnSeekBarChangeListener {
private boolean mActive = false;
private Runnable mUpdateTimeProgressBar = new Runnable() {
@Override
public void run() {
if (Globals.isPlaying) {
setProgress(Globals.mp.getCurrentPosition());
postDelayed(this, 100L);
}
}
};
public SelfUpdatingSeekbar(Context context, AttributeSet attrs) {
super(context, attrs);
setOnSeekBarChangeListener(this);
}
public void setActive() {
if (!mActive) {
mActive = true;
removeCallbacks(mUpdateTimeProgressBar);
setProgress(Globals.mp.getCurrentPosition());
setVisibility(View.VISIBLE);
postDelayed(mUpdateTimeProgressBar, 100L);
}
}
public void setInactive() {
if (mActive) {
mActive = false;
removeCallbacks(mUpdateTimeProgressBar);
setVisibility(View.INVISIBLE);
}
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
removeCallbacks(mUpdateTimeProgressBar);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
removeCallbacks(mUpdateTimeProgressBar);
Globals.mp.seekTo(getProgress());
postDelayed(mUpdateTimeProgressBar, 500);
}
}
Run Code Online (Sandbox Code Playgroud)
在适配器中getView(...)
:
if (Globals.isPlaying && Globals.pos == position) {
holder.seekbar.setActive();
} else {
holder.seekbar.setInactive();
}
Run Code Online (Sandbox Code Playgroud)
不用说,您需要在xml布局中使用此自定义实现:
<com.your.package.SelfUpdatingSeekbar
....
.... />
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
855 次 |
最近记录: |