I have an application that uses MediaPlayer class to play musics from internet. I used recyclerview, and on the each item , it has a play/puse button to start playing and pause the sound. How to change the play button to pause button when the user clicks on another items play button?
public class Adapter extends RecyclerView.Adapter<Adapter.Viewholder> {
private List<Track> tracks;
private Context context;
public Adapter(List<Track> tracks, Context context) {
this.tracks = tracks;
this.context = context;
}
#NonNull
#Override
public Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.track_item, parent, false);
return new Viewholder(view);
}
#Override
public void onBindViewHolder(#NonNull final Viewholder holder, final int position) {
holder.title.setText(tracks.get(position).getTitle());
holder.id.setText(tracks.get(position).getId());
Glide.with(context).load(tracks.get(position).getImgurl()).into(holder.trackImage);
holder.btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.btnPause.setVisibility(View.VISIBLE);
Intent intent = new Intent(context, Player.class);
intent.putExtra("URL", tracks.get(position).getMusicurl());
context.startService(intent);
}
});
holder.btnPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Player.killMediaPlayer();
holder.btnPause.setVisibility(View.INVISIBLE);
}
});
}
#Override
public int getItemCount() {
return tracks.size();
}
public static class Viewholder extends RecyclerView.ViewHolder {
TextView title, id;
ImageView trackImage;
ImageButton btnPlay;
public Viewholder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title);
id = itemView.findViewById(R.id.id);
trackImage = itemView.findViewById(R.id.trackImage);
btnPlay = itemView.findViewById(R.id.play);
}
}
}
Very simple just loop through your entire dataset and set all of them to pause except the current one.Then call notifyDatasetChanged();
your can use notifyDataSetChange() - it will update all recyclerView items
use notifyItemChanged(poition) - it will update the particular position.
NOTE : Suppose if your mobile screen has 8 items display at a moment and you
made 1th position as pause, the 9th position will show as pause.
To overcome this, try to compare the song_title/artist name before
notifying
you have to use notifyDataSetChanged() - it will reset all recyclerView items
then
using notifyItemChanged(poition) or mList.get(getAdapterPosition()) - it will update the specific position.
Here is sample code :
public class MainActivity extends AppCompatActivity {
private TrackAdapter trackAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.reycleView);
((SimpleItemAnimator) recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
trackAdapter = new TrackAdapter();
trackAdapter.setCallBack(new CallBackImpl());
trackAdapter.setTracks(getTracks());
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(trackAdapter);
}
private List<Track> tracks;
private List<Track> getTracks() {
tracks = new ArrayList<>();
for (int i = 0; i < 50; i++) {
Track track = new Track();
track.setTrackName(" Track " + i);
track.setPlaying(false);
tracks.add(track);
}
return tracks;
}
int currentPosition = -1;
private class CallBackImpl implements TrackAdapter.CallBack {
#Override
public void clicked(int position) {
Track track = tracks.get(position);
tracks.get(position).setPlaying(!track.isPlaying());
if (currentPosition >-1) {
track = tracks.get(currentPosition);
tracks.get(currentPosition).setPlaying(!track.isPlaying());
}
trackAdapter.setTracks(tracks);
trackAdapter.notifyItemChanged(currentPosition);
trackAdapter.notifyItemChanged(position);
currentPosition = position;
}
}
}
TrackAdapter.java
public class TrackAdapter extends RecyclerView.Adapter<TrackAdapter.VH> {
private int current;
public void setCallBack(CallBack callBack) {
this.callBack = callBack;
}
private CallBack callBack;
interface CallBack
{
void clicked(int position);
}
public void setTracks(List<Track> tracks) {
this.tracks = tracks;
}
private List<Track> tracks;
#Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout, parent, false);
return new VH(view);
}
#Override
public void onBindViewHolder(VH holder, int position) {
holder.setData(tracks.get(position));
}
#Override
public int getItemCount() {
if (tracks == null) {
return 0;
} else {
return tracks.size();
}
}
class VH extends RecyclerView.ViewHolder {
TextView textView;
TextView playView;
public VH(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.track);
playView = itemView.findViewById(R.id.trackplay);
playView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (callBack!=null)
{
callBack.clicked(getAdapterPosition());
}
}
});
}
void updateState(boolean isPlaying) {
if (isPlaying) {
current = getAdapterPosition();
playView.setText("Playing");
} else {
playView.setText("Stopped");
}
}
void setData(Track data) {
textView.setText(data.getTrackName());
updateState(data.isPlaying());
}
}
}
Track .java
public class Track {
private boolean isPlaying;
public String getTrackName() {
return trackName;
}
public void setTrackName(String trackName) {
this.trackName = trackName;
}
private String trackName;
public boolean isPlaying() {
return isPlaying;
}
public void setPlaying(boolean playing) {
isPlaying = playing;
}
}
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<TextView
android:id="#+id/track"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/trackplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Click is implemented on Stopped Text.
holder.btnPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Track.isPlaying()){
notifyItemChanged(currentItem, holder );
}
Track.setPlaying(true);
currentItem = holder.getAdapterPosition();
Log.i("TAG", "Position : " + currentItem);
holder.equalizer.setVisibility(View.VISIBLE);
holder.btnPause.setVisibility(View.VISIBLE);
holder.btnPlay.setVisibility(View.INVISIBLE);
Intent intent = new Intent(context, Player.class);
intent.putExtra("URL", tracks.get(position).getMusicurl());
intent.putExtra("ID", tracks.get(position).getId());
context.startService(intent);
}
});
Related
Hello friend a lot of search but not working plz help me.
my probem is delete all history from adaptor using on toolbar delete icon how to remove adaptor data
below code first show adaptor and mainactivity
public void removehistory(View view)
button click to remove items from adaptor how to solve this problem sorry for bad english and advance thanks
HistoryAdaptor
public class HistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ArrayList<Object> data;
private GenCallback<HistoryModel> clickListener;
private static final int NATIVE_AD = 1;
private static final int HISTORY_ITEM = 2;
private LayoutInflater inflater;
// private Button removedata;
public HistoryAdapter() {
this.data = new ArrayList<>();
inflater = (LayoutInflater) App.getInstance().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case NATIVE_AD:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ad_unified, null, false);
return new NativeAdHolder(view);
case HISTORY_ITEM:
default:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history, null, false);
return new ViewHolder(view);
}
// return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history, null, false));
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case NATIVE_AD:
((NativeAdHolder) holder).bind((UnifiedNativeAd) data.get(position));
break;
case HISTORY_ITEM:
default:
((ViewHolder) holder).bind((HistoryModel) data.get(position));
break;
}
}
#Override
public int getItemViewType(int position) {
if (data.get(position) instanceof UnifiedNativeAd) {
return NATIVE_AD;
} else {
return HISTORY_ITEM;
}
}
#Override
public int getItemCount() {
return data.size();
}
public void addItem(Object obj, int pos) {
this.data.add(pos, obj);
notifyItemInserted(pos);
}
public void updateData(ArrayList<HistoryModel> list) {
this.data.clear();
this.data.addAll(list);
notifyDataSetChanged();
}
public void clear() {
if (this.data != null && this.data.size() != 0) {
this.data.clear();
notifyDataSetChanged();
}
}
public void setClickListener(GenCallback<HistoryModel> clickListener) {
this.clickListener = clickListener;
}
public void showStarredOnly() {
/*Iterator<Object> iterator = data.iterator();
int pos = 0;
while (iterator.hasNext()) {
if (iterator.next() instanceof HistoryModel) {
HistoryModel historyModel = (HistoryModel) iterator.next();
if (!historyModel.isStarred()) {
iterator.remove();
// notifyItemRemoved(pos);
}
}
pos++;
}
notifyDataSetChanged();*/
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.tvFromLang)
TextView tvFromLang;
#BindView(R.id.tvFromText)
TextView tvFromText;
#BindView(R.id.tvToLang)
TextView tvToLang;
#BindView(R.id.tvToText)
TextView tvToText;
#BindView(R.id.ivStar)
ImageView ivStar;
#BindView(R.id.llMain)
CardView llMain;
#BindView(R.id.tvDate)
TextView tvDate;
public ViewHolder(#NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
llMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (clickListener != null) {
clickListener.onCallback((HistoryModel) data.get(getAdapterPosition()));
}
}
});
llMain.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
int pos = getAdapterPosition();
HistoryModel historyModel = (HistoryModel) data.get(pos);
boolean isStar = historyModel.isStarred();
String from = historyModel.getFromLang();
String to = historyModel.getToLang();
Dialogs.INSTANCE.showActionsDialog(llMain.getContext(), isStar, from, to, new HistoryActionCallback() {
#Override
public void onClickCopyFrom() {
Utils.copyText(historyModel.getFromText());
Logger.logFabric(Constants.Events.COPY_FROM);
}
#Override
public void onClickCopyTo() {
Utils.copyText(historyModel.getToText());
Logger.logFabric(Constants.Events.COPY_TO);
}
#Override
public void onClickStar() {
Logger.logFabric(Constants.Events.MARKED_AS_FAV);
historyModel.setStarred(!isStar);
notifyItemChanged(pos);
RoomRepository.getNew().updateHistoryItem(historyModel);
// notifyDataSetChanged();
}
#Override
public void onClickDelete() {
String message = "Are you sure you want to delete?";
Dialogs.INSTANCE.showConfirmationDialog(view.getContext(), message, new View.OnClickListener() {
#Override
public void onClick(View view) {
RoomRepository.getNew().deleteHistoryRecord(historyModel.getTimeStamp());
data.remove(pos);
notifyItemRemoved(pos);
Dialogs.INSTANCE.dismissDialog();
Logger.logFabric(Constants.Events.ITEM_DELETED);
}
});
}
});
return false;
}
});
}
public void bind(HistoryModel item) {
StringBuilder builder = new StringBuilder();
builder.append(item.getFromLang()).append("(").append(item.getFromCode()).append(")");
tvFromLang.setText(builder);
tvFromText.setText(item.getFromText());
builder.setLength(0);
builder.append(item.getToLang()).append("(").append(item.getToCode()).append(")");
tvToLang.setText(builder);
tvToText.setText(item.getToText());
String date = Utils.formatDate(item.getTimeStamp(), "EEE, MMM d, yyyy");
tvDate.setText(date);
ivStar.setVisibility(item.isStarred() ? View.VISIBLE : View.GONE);
}
MainActivity
public class HistoryActivity extends AppCompatActivity {
private HistoryAdapter mAdapter;
private ArrayList<Object> data;
private Activity mCurrentActivity;
private RecyclerView rvHistory;
private Button clearh;
private GenCallback<HistoryModel> clickListener;
private ArrayList<HistoryModel> datamodel = new ArrayList<>();
private ArrayList<String> arrayList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
rvHistory = findViewById(R.id.rvHistory);
ImageView imgb = findViewById(R.id.imgback);
initAdapter();
getAdapter();
imgb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
HistoryActivity.super.onBackPressed();
}
});
}
private void getAdapter() {
RoomRepository.getNew().getAllHistory(mCallback);
}
private void initAdapter() {
mAdapter = new HistoryAdapter();
LinearLayoutManager layoutManager = new LinearLayoutManager(mCurrentActivity);
rvHistory.setLayoutManager(layoutManager);
rvHistory.setAdapter(mAdapter);
}
private IRoomDataHandler mCallback = new RoomDataHandler() {
#Override
public void onGetAllHistory(ArrayList<HistoryModel> list) {
// if (isSafe()) {
mAdapter.updateData(list);
// showLoader(false);
// checkForNoData();
// if (AdUtils.getInstance().getNativeAd() != null) {
//
// }
}
#Override
public void onError(String error) {
// showLoader(false);
// checkForNoData();
}
};
public void removehistory(View view) {
//problem is here
mAdapter.notifyItemRemoved(i);
}
}
call clear() method from on click oh that button like this.
public void removehistory(View view) {
//problem is here
mAdapter.clear()
}
I have a RecyclerView filled with elements of the "Event" class. The class has parameters such as Date and Importance.
Now all Events in RecyclerView are displayed just like that.
I want to show Events by Date separately and also want to show Events by importance separately. I'll attach a picture to show what I mean.
I read that to do separation, for example, by dates, you need to make a separate adapter and viewholder. Question - if I want to split the same data array by importance, do I need to create another adapter?
And let's say I want to choose a grouping method. How can I do this and where?
My First RecyclerViewAdapter of Event
public class EventAdapter extends RecyclerView.Adapter<EventAdapter.EventViewHolder> {
private static final String TAG = "myLogs";
private List<Event> mEventList;
final SparseBooleanArray selectedItems = new SparseBooleanArray();
private int currentSelectedPos;
public List<Event> getEvents(){
return mEventList;
}
private EventAdapterListener itemClickListener;
public interface EventAdapterListener {
void onItemClick(int position);
void onItemLongClick(int position);
}
public void setListener(EventAdapterListener listener){
itemClickListener = listener;
}
private OnItemCheckedListener OnItemChecked;
public interface OnItemCheckedListener {
void onItemChecked(int position, boolean isImportant);
}
public void setOnItemCheckedListener (OnItemCheckedListener listener){
OnItemChecked = listener;
}
public static class EventViewHolder extends RecyclerView.ViewHolder{
public TextView TVtitle;
public TextView TVcomment;
public CheckBox CBimportance;
public TextView TVdate;
//public EventViewHolder(#NonNull View itemView, final EventAdapterListener listener) {
public EventViewHolder(#NonNull View itemView) {
super(itemView);
TVtitle = itemView.findViewById(R.id.tvTitle);
TVcomment = itemView.findViewById(R.id.tvComment);
CBimportance = itemView.findViewById(R.id.cbIconImportant);
TVdate = itemView.findViewById(R.id.tvDate);
}
}
public void removeItem(int position) {
mEventList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mEventList.size());
}
private static DateFormatSymbols myDateFormatSymbols = new DateFormatSymbols(){
#Override
public String[] getMonths() {
return new String[]{"января", "февраля", "марта", "апреля", "мая", "июня",
"июля", "августа", "сентября", "октября", "ноября", "декабря"};
}
};
public EventAdapter(ArrayList<Event> listEvent){
mEventList = listEvent;
}
#NonNull
#Override
public EventViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_cardview, parent, false);
//LayoutInflater inflater = LayoutInflater.from(parent.getContext());
//if (viewType == Constants.VIEWTYPE_GROUP){
//ViewGroup group = (ViewGroup) inflater.inflate(R.layout.group_layout, parent, false);
//GroupViewHolder
//}
return new EventViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull EventViewHolder holder, final int position) {
final Event item = mEventList.get(position);
holder.TVtitle.setText(item.getName());
holder.TVcomment.setText(item.getComment());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMMM", myDateFormatSymbols);
holder.TVdate.setText(simpleDateFormat.format(item.getDate()));
holder.CBimportance.setOnCheckedChangeListener(null);
holder.CBimportance.setChecked(item.getImportant());
holder.CBimportance.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
item.IsImportant = b;
OnItemChecked.onItemChecked(position, b);
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (selectedItems.size() > 0 && itemClickListener != null){
itemClickListener.onItemClick(position);
}
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if (itemClickListener != null){
itemClickListener.onItemLongClick(position);
}
return true;
}
});
if (currentSelectedPos == position) currentSelectedPos = -1;
}
#Override
public int getItemCount() {
return mEventList.size();
}
void deleteEvents(){
List<Event> events = new ArrayList<>();
for (Event event : mEventList){
if (event.getSelected())
events.add(event);
}
mEventList.removeAll(events);
notifyDataSetChanged();
currentSelectedPos = -1;
}
void toggleSelection(int position) {
currentSelectedPos = position;
if (selectedItems.get(position)) {
selectedItems.delete(position);
mEventList.get(position).setSelected(false);
} else {
selectedItems.put(position, true);
mEventList.get(position).setSelected(true);
}
notifyItemChanged(position);
}}
I have some problems with RecyclerView Adapter. I want to do the list with id index: 1,2,3... When an item is removed it should set every next item position to position-1. Like this: (for example delete number 3)
1|2|3|4|5 -> 1|2|3|4
It works perfectly when:
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
But this causes other errors with notifyItemRemoved().
When I set:
#Override
public long getItemId(int position) {
return 0;
}
#Override
public int getItemViewType(int position) {
return 0;
}
It has problems with item order after scrolling, with repeatability of numbers etc.
I'm stuck.
MainActivity.class
public class MainActivity extends AppCompatActivity {
private DatabaseHelper databaseHelper;
private EditText editText;
private Button showButton,saveButton;
private RecyclerView mainListRecyclerView;
private ArrayList<String>arrayList;
private MainListAdapter mainListAdapter;
private RecyclerView.LayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
showButton = (Button) findViewById(R.id.showButton);
saveButton = (Button) findViewById(R.id.saveButton);
mainListRecyclerView = (RecyclerView) findViewById(R.id.listView);
databaseHelper = new DatabaseHelper(this);
arrayList = new ArrayList<>(20);
layoutManager = new LinearLayoutManager(this);
mainListRecyclerView.setLayoutManager(layoutManager);
mainListAdapter = new MainListAdapter(arrayList,this);
mainListAdapter.setHasStableIds(false);
mainListRecyclerView.setAdapter(mainListAdapter);
mainListAdapter.notifyDataSetChanged();
showButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, FinalListActivity.class);
intent.putExtra("productList",arrayList);
MainActivity.this.startActivity(intent);
}
});
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId==EditorInfo.IME_ACTION_DONE) {
addItem();
}
return true;
}
});
}
public void addData(String newItem){
boolean insertData = databaseHelper.addData(newItem);
if(insertData){
toastMessage("Item successfully inserted!");
}
else {
toastMessage("Something is wrong");
}
}
public void removeData(String itemToRemove){
boolean removeData = databaseHelper.removeData(itemToRemove);
if(removeData){
toastMessage("Item successfully deleted!");
}
else {
toastMessage("Something is wrong");
}
}
public void toastMessage(String message){
Toast.makeText(this,message,Toast.LENGTH_SHORT).show();
}
public void addItem(){
String newItem = editText.getText().toString();
if(newItem.length()!=0) {
addData(newItem);
arrayList.add(newItem);
editText.setText("");
editText.requestFocus();
mainListAdapter.notifyItemInserted(arrayList.size()-1);
}
else{
toastMessage("You must put something in the text field");
}
}
public void removeItem(int position){
if(mainListAdapter.getItemCount()!=0){
removeData(arrayList.get(position));
arrayList.remove(position);
mainListAdapter.notifyItemRemoved(position);
}
}
}
Adapter class
public class MainListAdapter extends
RecyclerView.Adapter<MainListAdapter.MyViewHolder> {
private ArrayList<String> mDataset;
private MainActivity mainActivity;
public MainListAdapter(ArrayList<String> mDataset, MainActivity
mainActivity) {
this.mDataset = mDataset;
this.mainActivity = mainActivity;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public int getItemViewType(int position) {
return 0;
}
#Override
public int getItemCount() {
return mDataset.size();
}
#Override
public void onBindViewHolder(final MyViewHolder holder,final int position) {
holder.listTextView1.setText(holder.getAdapterPosition()+"");
holder.listTextView2.setText(mDataset.get(position));
holder.listButtonViewDel.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
int currentPosition = holder.getAdapterPosition();
if(currentPosition!=-1)
mainActivity.removeItem(currentPosition);
}
});
}
public class MyViewHolder extends RecyclerView.ViewHolder {
final public TextView listTextView1;
final public TextView listTextView2;
final public Button listButtonViewDel;
public MyViewHolder(View view) {
super(view);
listTextView1 = (TextView) view.findViewById(R.id.listTextView1);
listTextView2 = (TextView) view.findViewById(R.id.listTextView2);
listButtonViewDel = (Button) view.findViewById(R.id.listButtonViewDel);
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_list_layout, parent, false);
return new MyViewHolder(view);
}
}
Add this lines To removeItem function in MainActivity.java
public void removeItem(int position){
if(mainListAdapter.getItemCount()!=0){
removeData(arrayList.get(position));
arrayList.remove(position);
mainListAdapter.notifyItemRemoved(position);
arrayList.remove(position); // add this line
mainListAdapter.update(arrayList); // add this line
}
}
And add update function to your MainListAdapter.java like this
public void update(ArrayList<String> mDataset){
this.mDataset = mDataset
notifyDataSetChanged();
}
For show animation try this function (I suggest you to set all function about adapter in adapter)
public void update(ArrayList<String> mDataset,int position){
this.mDataset = mDataset
notifyItemRangeChanged(position,mDataset.size);
}
In your removeItem() method,
You have mainListAdapter.notifyItemRemoved(position); and it will only inform the item is removed.
You need to put a line inside this method at end as mainListAdapter.notifyDataSetChanged().
It reminds adapter to reset the list on every change.
you can set null to mainListRecyclerVie wadapter and bind again when remove items !
mainListRecyclerVie.setAdapter(null);
and bind again
I've implemented to my Android app multiple countdown timers with Service.
CountDownTimer is running with service, thus data to fragment is being passed with BroadcastReceiver.
I would like to add each timer as a separate item to the RecyclerView in the fragment and be able to update it as timer is ticking and also to control it - pause, resume, add 1 min and delete.
At the moment the problem is that each second that timer is running, new item is added to RecyclerView and I'm not able to control it - pause, resume and ect.
Service Class:
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.START_FOREGROUND_ACTION)){
HandlerThread thread = new HandlerThread("ServiceStartArguments",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.setName(nameOfFood);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
Thread.currentThread().setName(nameOfFood);
try {
showCountDownTimer(enteredTimeFormatted);
} catch (Exception e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
stopSelf(msg.arg1);
}
private void showCountDownTimer(long number) {
String normalStartTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(number),
TimeUnit.MILLISECONDS.toMinutes(number) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(number)),
TimeUnit.MILLISECONDS.toSeconds(number) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(number)));
Intent timerStartInfoIntent = new Intent(TIMER_START_INFO);
timerStartInfoIntent.putExtra("VALUE", normalStartTime);
timerStartInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerStartInfoIntent);
CountDownTimer timer = new CountDownTimer(number, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
counter = millisUntilFinished / 1000;
normalTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(timeLeft),
TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", normalTime);
timerInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
}
#Override
public void onFinish() {
counter = 0;
Intent timerFinishInfoIntent = new Intent(TIMER_FINISH_INFO);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerFinishInfoIntent);
}
};
timer.start();
}
Adapter Class:
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
private final List<MyViewHolder> listHolder;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
listHolder = new ArrayList<>();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
ModelTimer mModelTimer;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
public void setData (ModelTimer modelTimer){
this.mModelTimer = modelTimer;
timerTextView.setText(modelTimer.expirationTime);
nameTextView.setText(modelTimer.name);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.setData(mModelTimerList.get(position));
synchronized (listHolder){
listHolder.add(holder);
}
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}
Here I tried to create a method that will be upgrading each second a timer on specific position instead of adding new item to RecyclerView each time that timer is ticking.
public void swap(List<ModelTimer> modelTimerList){
mModelTimerList.clear();
mModelTimerList.addAll(modelTimerList);
notifyItemChanged(???);
}
public void delete() {
mModelTimerList.clear();
notifyDataSetChanged();
}
}
Fragment with RecyclerView:
public class ActiveTimersFragment extends Fragment {
private RecyclerView mRecyclerView;
private TimerRecyclerViewAdapter mAdapter;
private ArrayList<ModelTimer> listOfTimers;
private TimerStatusReceiver mTimerStatusReceiver;
private static final String ARG_SECTION_NUMBER = "section_number";
public ActiveTimersFragment() {
}
public static ActiveTimersFragment newInstance(int sectionNumber) {
ActiveTimersFragment activeTimersFragment = new ActiveTimersFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
activeTimersFragment.setArguments(args);
return activeTimersFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_active_timers, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_active_timers_recycler_view);
mTimerStatusReceiver = new TimerStatusReceiver();
listOfTimers = new ArrayList<>();
return view;
}
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_START_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_FINISH_INFO));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
private class TimerStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
ModelTimer modelTimer = new ModelTimer();
if (intent.hasExtra("VALUE")) {
modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
}
if (intent.hasExtra("NAME_FOOD")) {
modelTimer.setName(intent.getStringExtra("NAME_FOOD"));
}
listOfTimers.add(modelTimer);
mAdapter = new TimerRecyclerViewAdapter(listOfTimers, getActivity());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// Not working
// mAdapter.swap(listOfTimers);
mRecyclerView.setAdapter(mAdapter);
}
if (intent != null && intent.getAction().equals(NotificationService.TIMER_FINISH_INFO)) {
mAdapter.delete();
}
}
}
}
Your whole implementation of recyclerview adapter is wrong. In onBindViewHolder() you are adding new item. onBindViewHolder is called when RecyclerView tries to show new item. So it keeps on iterating, if you add new item in onBindViewHolder. Also, you should use the onBindViewHolder to set the views values in ViewHolder class. Check the whole adapter implementation.
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
ModelTimer modelTimer=mModelTimerList.get(position);
holder.timerTextView.setText(modelTimer.expirationTime);
holder.nameTextView.setText(modelTimer.name);
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}
How can handle with this situation -> I have a list of itens in a recyclerView and I want to choose one of those option: green, yellow or red face to get the value of object from list item I chose
So I thought something like bellow, but when I select one of those faces anything happens. I think that button click listener doesn't work. Please someone can drive me to a better suggestion that works, give me an example or could me tell what am I doing wrong?
My adapter
public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.LikeItemViewHolder> {
private List<Goals> goalsList;
private SparseBooleanArray selectedItems;
public LikeListAdapter(List<Goals> goalsList) {
this.goalsList = goalsList;
}
#Override
public LikeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.recycler_item_like, parent, false);
return new LikeItemViewHolder(view);
}
#Override
public void onBindViewHolder(LikeItemViewHolder holder, int position) {
final Goals goals = goalsList.get(position);
if (goals != null && getItemCount() > 0) {
holder.goalsDescriptionTextView.setText(goals.getDescription());
holder.happyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("fretgr", "get Green Point = " + goals.getGreenPoint());
setToggleSelection(1);
}
});
holder.sosoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("rtret", "get Yellow Point = " + goals.getYellowPoint());
setToggleSelection(2);
}
});
holder.angryButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("ewwr", "get Red Point = " + goals.getRedPoint());
setToggleSelection(3);
}
});
}
}
#Override
public int getItemCount() {
return goalsList.size();
}
public class LikeItemViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.description_goalsTextView)
TextView goalsDescriptionTextView;
#Bind(R.id.happy)
ImageView happyButton;
#Bind(R.id.soso)
ImageView sosoButton;
#Bind(R.id.angry)
ImageView angryButton;
public LikeItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
// method to access in activity after updating selection
public List<Goals> getGoalsList() {
return goalsList;
}
public void setToggleSelection(int pointType){
selectedItems = new SparseBooleanArray();
if (selectedItems.get(pointType, false)) {
selectedItems.delete(pointType);
} else {
selectedItems.put(pointType, true);
}
notifyItemChanged(pointType);
}
public int getToggleSelection(){
return 0;
}
}
My Fragment
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
assocGoalsRecyclerView.setLayoutManager(layoutManager);
assocGoalsRecyclerView.setHasFixedSize(true);
likeListAdapter = new LikeListAdapter(associateList);
assocGoalsRecyclerView.setAdapter(likeListAdapter);
assocGoalsRecyclerView.addOnItemTouchListener(RecycleTouchListener);
private RecyclerView.OnItemTouchListener RecycleTouchListener = new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = assocGoalsRecyclerView.findChildViewUnder(e.getX(), e.getY());
if(child!=null && mGestureDetector.onTouchEvent(e)){
final int position = assocGoalsRecyclerView.getChildAdapterPosition(child);
final Goals goals = associateList.get(position);
final Categories c = categoriesList.get(position);
final int type = likeListAdapter.getToggleSelection();
return true;
}
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) { }
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { }
};
I found an answer based in another responses and sugestions!!! Android: handling clicks on image view inside recycler's view item using touch framework
In My Fragment
Snippet from fragment:
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
assocGoalsRecyclerView.setLayoutManager(layoutManager);
// assocGoalsRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
assocGoalsRecyclerView.setHasFixedSize(true);
likeListAdapter = new LikeListAdapter(associateList, onItemClickCallback);
assocGoalsRecyclerView.setAdapter(likeListAdapter);
public static class OnItemClickListener implements View.OnClickListener {
private int position;
private OnItemClickCallback onItemClickCallback;
public OnItemClickListener(int position, OnItemClickCallback onItemClickCallback) {
this.position = position;
this.onItemClickCallback = onItemClickCallback;
}
#Override
public void onClick(View view) {
onItemClickCallback.onItemClicked(view, position);
}
public interface OnItemClickCallback {
void onItemClicked(View view, int position);
}
}
private OnItemClickListener.OnItemClickCallback onItemClickCallback = new OnItemClickListener.OnItemClickCallback() {
#Override
public void onItemClicked(View view, int position) {
switch(view.getId()){
case R.id.happy:
Log.e("rtetre", "happy assessed and position is = " + position);
break;
case R.id.soso:
Log.e("rwere", "soso assessed and position is = " + position);
break;
case R.id.angry:
Log.e("dfrefgt", "angry assessed and position is = " + position);
break;
}
}
};
In My adapter
public class LikeListAdapter extends RecyclerView.Adapter<LikeListAdapter.LikeItemViewHolder> {
private List<Goals> goalsList;
private LikeFragment.OnItemClickListener.OnItemClickCallback onItemClickCallback;
public LikeListAdapter(List<Goals> goalsList, LikeFragment.OnItemClickListener.OnItemClickCallback onItemClickCallback) {
this.goalsList = goalsList;
this.onItemClickCallback = onItemClickCallback;
}
#Override
public LikeItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.recycler_item_like, parent, false);
LikeItemViewHolder likeItemViewHolder = new LikeItemViewHolder(view);
return likeItemViewHolder;
}
#Override
public void onBindViewHolder(LikeItemViewHolder holder, int position) {
final Goals goals = goalsList.get(position);
if (goals != null && getItemCount() > 0) {
holder.goalsDescriptionTextView.setText(goals.getDescription());
holder.happyButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
holder.sosoButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
holder.angryButton.setOnClickListener(new LikeFragment.OnItemClickListener(position, onItemClickCallback));
}
}
#Override
public int getItemCount() {
return goalsList.size();
}
public static class LikeItemViewHolder extends RecyclerView.ViewHolder {
#Bind(R.id.description_goalsTextView)
TextView goalsDescriptionTextView;
#Bind(R.id.happy)
ImageView happyButton;
#Bind(R.id.soso)
ImageView sosoButton;
#Bind(R.id.angry)
ImageView angryButton;
public LikeItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}