Reputation: 10273
I have a ListView
with items containing each one a SeekBar
.
What I want to achieve is that when one of the SeekBar
s is slowly slided, the rest of the SeekBar
s gracefully slide at the same time (this is, I want the events of one items to make effect on the rest of the list items).
I tried to store all the views in an array of views inside the adapter, but I was getting unexpected and unpredictable behavior (I guess it is related to the way ListView manages the child items internally).
Any hint on how this should be properly done?
Thank you very much!
Upvotes: 1
Views: 129
Reputation: 7257
You can do this with fancy stuff like RxJava or event bus, or without external dependencies:
class MyObjAdapter extends RecyclerView.Adapter<MyObjAdapter.MyObjViewHolder> {
class MyObjViewHolder extends RecyclerView.ViewHolder {
SeekBar bar;
MyObjViewHolder(View itemView, SeekBar.OnSeekBarChangeListener listener) {
super(itemView);
bar = itemView.findViewById(R.id.bar);
bar.setOnSeekBarChangeListener(listener);
}
}
private LinearLayoutManager layoutManager;
private int value = 0;
private SeekBar.OnSeekBarChangeListener listener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
value = progress;
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
notifyItemRangeChanged(firstVisiblePosition,
layoutManager.findLastVisibleItemPosition() - firstVisiblePosition + 1);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
public MyObjAdapter(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
@Override
public MyObjViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item, parent, false);
return new MyObjViewHolder(view, listener);
}
@Override
public void onBindViewHolder(MyObjViewHolder holder, int position) {
holder.bar.setProgress(value);
}
@Override
public int getItemCount() {
return 100;
}
}
Upvotes: 1
Reputation: 62199
I would solve the problem using RxJava.
Basically, you have a stream of data (Seekbar
's current position) and have arbitrary amount of subscribers (each Seekbar
of each row).
You need some kind of Observable
, that possesses following features:
Observable
Turns out BehaviorSubject
is the one that you need.
So, having declared a BehaviorSubject
this was:
BehaviorSubject<Integer> subject = BehaviorSubject.createDefault(0); // default value is 0
Now anytime any Seekbar
's value is changed just perform subject.onNext(currentPosition)
.
As soon as the view is being shown on the screen - subscribe to the stream:
Disposable d = subject.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
seekbar.setProgress(integer);
}
)
When the view is being recycled - dispose from the Disposable
:
d.dispose();
Upvotes: 1