Hi I'm building PlaybackSupportFragment and after adding extra row below player controls, the Presenter's onClickEvent does not work, I mean does not catches at all.
ArrayObjectAdapter episodeRow = new ArrayObjectAdapter(new EpisodePresenter(mother));
for(Episode episode : episodes)
episodeRow.add(episode);
superAdapter.add(new ListRow(new HeaderItem(0, "Episodes"), episodeRow));
setAdapter(superAdapter);
and EpisodePresenter itself is (class of course extends android.support.v17.leanback.widget.Presenter):
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
TextView view = new TextView(parent.getContext());
view.setLayoutParams(new ViewGroup.LayoutParams(315, 175));
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.setBackgroundColor(context.getResources().getColor(R.color.default_background));
view.setTextColor(Color.WHITE);
view.setGravity(Gravity.CENTER);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, Object item) {
TextView vHolder = (TextView) viewHolder.view;
final Episode model = (Episode) item;
vHolder.setText(model.name);
vHolder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Does not work at all
Toast.makeText(context, "dsadas", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onUnbindViewHolder(ViewHolder viewHolder) {
}
What is a solution to that?
Fixed by using setOnEditorActionListener instead of onClickListener
Related
I've got a RecyclerView that needs to update in real-time when content is received. It successfully shows all the content at first load. When attempting to add a new item dynamically, it makes no difference. Is there anything I'm doing wrong here? Much appreciated!
MainActivity:
RecyclerView rvClips;
ClipboardRVAdapter adapter;
ArrayList<Clip> clips = new ArrayList<>();
private void SetupRV() {
adapter = new ClipboardRVAdapter(clips);
rvClips.setAdapter(adapter);
adapter.setClickListener(this);
rvClips.setLayoutManager(new LinearLayoutManager(getActivity()));
}
//this method gets called everytime a new item is received. I confirmed that it gets called.
public void OnNewClipReceived(Clip clip) {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
Adapter:
Standard adapter code. Simply shows all the items in the recyclerview.
public class ClipboardRVAdapter extends RecyclerView.Adapter<ClipboardRVAdapter.ViewHolder> {
private ItemClickListener mClickListener;
ArrayList<Clip> clips;
public ClipboardRVAdapter(ArrayList<Clip> clips) {
this.clips = clips;
}
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_clipboard_clip, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Clip clip = clips.get(position);
holder.tvClipTitle.setText(clip.content);
}
#Override
public int getItemCount() {
return clips.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvClipTitle;
public ViewHolder(View itemView) {
super(itemView);
tvClipTitle = itemView.findViewById(R.id.tvClipTitle);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
}
Since you mentioned 'realtime', I'm guessing this could be a thread issue. Your code seems correct. It could be that the adapter needs to be refreshed in a runOnUiThread function. Try this:
public void OnNewClipReceived(Clip clip) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
});
}
You would need this method in your RecyclerView adapter.
void addNewClip(Clip clip, int index) {
this.clips.add(index, clip);
notifyItemInserted(index);
}
Adding to clips(MainActivity's) won't make a difference because your adapter has it own ArrayList to work with.
I have RecyclerView in my Main Activity. I want to change different fragments after clicking on different recyclerview Items. I try this by using position from onbindviewholder() but i am not able to change the fragment when i click on recyclerview items. I am not getting any error but at the same time nothing is happening onclick of recyclerview. Please check my code and tell me where i am wrong or which line of code i am missing.
RecyclerAdapter Code:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
ArrayList<NewModel> newModels;
Context context;
public RecyclerAdapter(ArrayList<NewModel>newModels, Context context){
this.newModels = newModels;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recy_layout, parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
holder.imageView.setImageResource(newModels.get(position).getImg());
holder.textView.setText(newModels.get(position).getText());
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(position ==1){
((FragmentActivity)context).getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, new FirstFragment());
}
else if(position ==2){
((FragmentActivity)context).getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, new SecondFragment());
}
}
});
}
#Override
public int getItemCount() {
return newModels.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.cirlceimg);
textView = itemView.findViewById(R.id.text1);
}
}
}
you forgot to call commit()
do this:
(((FragmentActivity)context).getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, new SecondFragment()).commit();
Fragment is not rendered until you call commit() on the transaction , because transaction use builder pattern and in builder pattern there is a method to say that i don't want to do anything else just create the object, normally these method are name create() , build(), and commit() in this case
You can handle the onClickListener from your activity using callback implementation with an interface.
Interface:
public interface OnItemClickListener {
void onItemClick(int position);
}
Add the listener to your adapter's constructor
ArrayList<NewModel> newModels;
Context context;
private final OnItemClickListener listener;
public RecyclerAdapter(ArrayList<NewModel>newModels, Context context, OnItemClickListener listener){
this.newModels = newModels;
this.context = context;
this.listener = listener;
}
In your onBindViewHolder set the clicklistener
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
holder.imageView.setImageResource(newModels.get(position).getImg());
holder.textView.setText(newModels.get(position).getText());
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(position);
}
});
}
In your activity:
RecyclerAdapter rvAdapter = new RecyclerAdapter(newModels, this, new RecyclerAdapter.OnItemClickListener() {
#Override public void onItemClick(int item) {
if(position ==1){
getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, new FirstFragment()).commit();;}
else if(position ==2){
getSupportFragmentManager().beginTransaction().replace(R.id.framelayout, new SecondFragment()).commit();;
}
}});
recycler.setAdapter(rvAdapter);
Inside onBindViewHolder
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(position ==1){
((FragmentActivity)context).getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, new FirstFragment()).addToBackStack(null).commit();
}
else if(position ==2){
((FragmentActivity)context).getSupportFragmentManager().beginTransaction()
.replace(R.id.framelayout, new SecondFragment()).addToBackStack(null).commit();
}
}
});
}
Hope this helps you.
I need to call an Interstitial in this Activity by clicking on an item in the list that comes from my Adapter.
public class SoundRecyclerAdapter extends RecyclerView.Adapter<SoundRecyclerAdapter.SoundViewHolder> {
private final ArrayList<SoundObject> soundObjects;
SoundRecyclerAdapter(ArrayList<SoundObject> soundObjects) {
this.soundObjects = soundObjects;
}
#NonNull
#Override
public SoundViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.sound_item, parent, false);
return new SoundViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull SoundViewHolder holder, int position) {
final SoundObject object = soundObjects.get(position);
final Integer soundID = object.getItemID();
holder.itemTextView.setText(object.getItemName());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I tried calling the interstitial here, but to no avail
EventHandlerClass.startMediaPlayer(v, soundID);
}
});
// Handle actions when the user presses a sound button
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
EventHandlerClass.popupManager(v, object);
return true;
}
});
}
#Override
public int getItemCount() {
return soundObjects.size();
}
class SoundViewHolder extends RecyclerView.ViewHolder {
final TextView itemTextView;
SoundViewHolder(View itemView) {
super(itemView);
itemTextView = itemView.findViewById(R.id.textViewItem);
}
}
}
Pass context as parameter of adapter's constructor:
private Context context;
SoundRecyclerAdapter(Context context, ArrayList<SoundObject> soundObjects) {
this.soundObjects = soundObjects;
this.context = context;
}
and use it in click handler
Use this code in the setOnClickListener() method:
mInterstitialAd = new InterstitialAd(SoundRecyclerAdapter.this);
Then add the adrequests and load the ad.
in my adapter I have the problem that if I have defined a String before the onClickListener I cannot change it later in the onClickListener. I can set it to invisible which works perfect however I cannot change it.
I want that if a user clicks on the image, a second image should replace the first one, but I cannot either change the image in a imageview, I suggest that it is the same problem as with the String which I cannot change.
Thanks for any help!
private List<cards> listItems;
private Context context;
public arrayAdapter(List<cards> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
return new ViewHolder(v);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, int i) {
final cards currentItem = listItems.get(i);
viewHolder.name.setText(currentItem.getName());
viewHolder.comment.setText(currentItem.getComment());
Picasso.get().load(currentItem.getProfileImageUrl()).into(viewHolder.image);
viewHolder.name.setText("this work"); // here it works
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Try this
currentItem.setName("New text");
notifyDataSetChanged();
//viewHolder.name.setText("New text"); // this does not work
// viewHolder.name.setVisibility(View.INVISIBLE); this does work
Picasso.get().load(currentItem.getProfileImageUrl2()).into(viewHolder.image); // does not work
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView name, comment, howMany;
public ImageView image;
/**
* #param itemView
*/
ViewHolder(#NonNull View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.name);
image = (ImageView) itemView.findViewById(R.id.image);
comment = (TextView) itemView.findViewById(R.id.commentText);
}
}
}
You should call notifyItemChanged with the corresponding position.
#Override
public void onBindViewHolder(final ViewHolder viewHolder, int position) {
final cards currentItem = listItems.get(i);
viewHolder.name.setText(currentItem.getName());
viewHolder.comment.setText(currentItem.getComment());
Picasso.get().load(currentItem.getProfileImageUrl()).into(viewHolder.image);
viewHolder.name.setText("this work"); // here it works
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.name.setText("New text"); // this does not work
// viewHolder.name.setVisibility(View.INVISIBLE); this does work
Picasso.get().load(currentItem.getProfileImageUrl2()).into(viewHolder.image); // does not work
notifyItemChanged(position);
}
});
}
change value in you list at particular position and then notifyItemChanged(position);
in your click event write this:
currentItem.setName("abc");
notifyItemChanged(position)
In the data model you have keep a variable which indicates the current profile image.
for a example
class cards {
String name;
String comment;
....
boolean profileImageChanged;
}
then inside onBindViewHolder
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, int i) {
....
if(currentItem.profileImageChanged){
Picasso.get()
.load(currentItem.getProfileImageUrl()).into(viewHolder.image);
} else {
Picasso.get()
.load(currentItem.getProfileImageUrl2()).into(viewHolder.image);
}
viewHolder.name.setText("this work"); // here it works
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.name.setText("New text"); // this does not work
// viewHolder.name.setVisibility(View.INVISIBLE); this does work
notifyItemChanged(position);
}
});
}
Hi you can go with this approach also.
#Override
public void onBindViewHolder(final ViewHolder viewHolder, int position) {
final cards currentItem = listItems.get(i);
viewHolder.name.setText(currentItem.getName());
viewHolder.comment.setText(currentItem.getComment());
Picasso.get().load(currentItem.getProfileImageUrl()).into(viewHolder.image);
viewHolder.name.setText("this work"); // here it works
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ViewHolder viewNewHolder=viewHolder
viewNewHolder.name.setText("New text");
Picasso.get().load(currentItem.getProfileImageUrl2()).into(viewNewHolder.image);
}
});
}
I have used it its working.
*******All The Best*********
to begin I would thanks those who help noobi dev like me :p! Let's say that I have a Recyclerview in which every unit element has two images. Actually I am able to find the indice of the unit element clicked to fire the good evenment thanks to this little trick in MyAdapter:
#Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model, parent, false);
final MyHolder holder = new MyHolder(v);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
listener.onItemClick(v, holder.getAdapterPosition());
}
});
return holder;
}
Then I start the event this way in the activity:
MyAdapter adapter = new MyAdapter(this, countryCollection.getCountryArray(), new CustomItemClickListener() {
#Override
public void onItemClick(View v, int position) {
//Launch the events
ArrayList<String> languageCodeArray = countryCollection.getLanguageCodeArray();
ArrayList<String> countryIdArray = countryCollection.getCountryIdArray();
if(position >0){
String languageCode = languageCodeArray.get(position-1);
String countryId = countryIdArray.get(position-1);
Intent intent = new Intent(context, LetsSpeakActivity.class);
intent.putExtra("country_id", countryId);
intent.putExtra("language_code", languageCode);
startActivity(intent);
}
}
});
rv.setAdapter(adapter);
But how can I différentiate the two images of my RecyclerView in order to fire the good event? I've been searching for a while how to differentiate a click on the left or right side of the screen but it is obviously not the right way to do ! Any help would be lovely, I am really stuck...
Supposing you have defined both ImageView in your MyHolder class, you could set OnClickListener on both of them in your holder constructor :
public class MyHolder extends RecyclerView.ViewHolder {
public ImageView imageLeft;
public ImageView imageRight;
public CustomItemClickListener listenerLeft;
public CustomItemClickListener listenerRight;
public MyHolder(View v, CustomItemClickListener listenerLeft, CustomItemClickListener listenerRight) {
super(v);
this.listenerLeft = listenerLeft;
this.listenerRight = listenerRight;
imageLeft = v.findViewById(R.id.image_left);
imageRight = v.findViewById(R.id.image_right);
imageLeft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listenerLeft.onItemClick(v, getPosition());
}
});
imageRight.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listenerRight.onItemClick(v, getPosition());
}
});
}
}
while injecting both listener in onCreateViewHolder :
#Override
public MyAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.model, parent, false);
return new MyHolder(v, mImageLeftListener, mImageRightListener);
}
You can introduce both of these listener in your Adapter constructor like you did with listener
Or if you want to pass only one listener, you can define your CustomItemClickListener interface with 2 methods (or just 1 with an additional param to differentiate the image clicked) :
public interface CustomItemClickListener {
void onLeftImageClick(View view, int position);
void onRightImageClick(View view, int position);
}