Unable to show popmenu on RecyclerView item click - java

I have menu option in Recyclerview item row when user clicks on that row element then I want to show pop menu. I have implemented this functionality and on click message is showing on log but popmenu is not showing up.
Below is my code:
public class PdfAdapter extends RecyclerView.Adapter<PdfAdapter.ViewHolder> {
Context context;
List<Pdfs> pdfList;
public PdfAdapter(Context context, List<Pdfs> pdfList) {
this.context = context;
this.pdfList = pdfList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.pdf_item_row,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Pdfs model = pdfList.get(position);
holder.pdfName.setText(model.getFilenamename());
holder.datTime.setText(model.getDatetime());
holder.menu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("clik","Hello");
PopupMenu popupMenu = new PopupMenu(context,holder.menu);
popupMenu.inflate(R.menu.row_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.itemShare:
break;
case R.id.itemDel:
break;
case R.id.itemDownload:
Toast.makeText(context,model.getFileurl(),Toast.LENGTH_SHORT).show();
break;
}
return false;
}
});
}
});
}
#Override
public int getItemCount() {
return pdfList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView pdfName,menu,datTime;
public ViewHolder(#NonNull View itemView) {
super(itemView);
pdfName = itemView.findViewById(R.id.pdfName);
menu = itemView.findViewById(R.id.menu);
datTime = itemView.findViewById(R.id.datTime);
}
}
}
What am I doing wrong?

You forgot to call .show() method on popupMenu.
Add below line at last inside click listener.
popupMenu.show();

Related

Disable buttons in recycler view after clicking

I have a recycler view, which consists of edittext and buttons for each view. I would like to have functionality in such a way that if I enter some text or attach an image for a view, then some of the buttons' functionality needs to be disabled in that view as soon as I click the button.
With the below code, I can attach images when ProofClick function is called via the interface, and then I set the button as disabled for the same position, but the button is not disabled, and I can attach images to the same view twice, which I do not want.
Adapter class:
// Check if the button is clicked and disable
private boolean clicked = false;
public InsStepsContentAdapter(List<InspectonScroll> scrollList,
ClickOnRecycle clickOnRecycle, String[] options) {
this.scrollList = scrollList;
this.clickOnRecycle = clickOnRecycle;
this.options = options;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_recycler_steps, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setIsRecyclable(false);
holder.progressbar.setMax(scrollList.size());
holder.title.setText(scrollList.get(position).getSteps().get(position).getTitle());
holder.btnAttach.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(clicked){
clicked = true;
clickOnRecycle.ProofClick(holder.getAdapterPosition());
holder.btnAttach.setEnabled(true);
} else{
holder.btnAttach.setEnabled(false);
}
}
});
}
public int getItemCount() {
return scrollList.size();
}
#Override
public int getItemViewType(int position) {
return position;
}
public void updateList(List<ScrollList> scrollList){
this.scrollList = scrollList;
notifyDataSetChanged();
}
Model class:
public class InspectonScroll {
private List<Steps> Steps = new ArrayList<>();
public List<Steps> getSteps() {
return steps;
}
public void setSteps(List<Steps> steps) {
this.steps = steps;
}
}
ButtonAdapter
public class ButtonAdapter extends RecyclerView.Adapter<ButtonAdapter.ViewHolder> {
Activity activity;
ArrayList<ButtonModel> arrayList;
public ButtonAdapter(Activity activity, ArrayList<ButtonModel> arrayList) {
this.activity = activity;
this.arrayList = arrayList;
}
#NonNull
#Override
public ButtonAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(activity.getLayoutInflater().inflate(R.layout.row_item,parent,false));
}
#Override
public void onBindViewHolder(#NonNull ButtonAdapter.ViewHolder holder, int position) {
holder.button.setText("item"+position);
ButtonModel item = arrayList.get(position);
holder.button.setEnabled(item.isEnabled);
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(item.isEnabled){
item.isEnabled = false;
notifyDataSetChanged();
}
Toast.makeText(activity, "Clicked", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
Button button;
public ViewHolder(#NonNull View itemView) {
super(itemView);
button = itemView.findViewById(R.id.button);
}
}
}
ButtonModel
public class ButtonModel {
boolean isEnabled = true;
}
one thing can be done here is maintaining the state of the button in the model as shown in the example and by using that state we can enable or disable the button in the onBindViewHolder method .

How to implement mini equalizer on selected item of RecyclerView?

I have a recyclerview whose listitem is designed as follows
LinearLayout(Horizontal)
ImageView
TextView
ImageButton(PlayButton)
EqualizerView(Invisible)
Now when I click on PlayButton, it should hide and equalizer show be displayed and if I scroll the list, equalizer should stay on selected item only.
However, I am facing problem that EqualizerView is being displayed at interval of 10 items. That is if I click on 3rd item then equalizer will be displayed on 3rd,13th and so on..
I am using this https://github.com/claucookie/mini-equalizer-library-android library for implementing mini equalizer.
public class StationViewAdapter extends RecyclerView.Adapter<StationViewAdapter.StationViewHolder> {
List<Station> statons;
final private ListItemClickListener mOnClickListener;
public StationViewAdapter (List<Station> s, ListItemClickListener l)
{
statons = s;
mOnClickListener = l;
}
#NonNull
#Override
public StationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,parent,false);
return new StationViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull final StationViewHolder holder, int position) {
Station station = statons.get(position);
if(!station.getArtwork().isEmpty() && station.getArtwork() != null)
{
try{
Picasso.get().load(Uri.parse(station.getArtwork()))
// .placeholder(R.mipmap.ic_launcher)
.into(holder.stationArtwork);
} catch (Exception e) {
e.printStackTrace();
holder.stationArtwork.setImageResource(R.mipmap.ic_launcher);
}
}
else
holder.stationArtwork.setImageResource(R.mipmap.ic_launcher);
holder.stationName.setText(station.getName());
}
#Override
public int getItemCount() {
return statons.size();
}
public class StationViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView stationArtwork;
TextView stationName;
ImageButton stationPlayButton;
EqualizerView equalizerView;
int selectedItem;
public StationViewHolder(#NonNull View itemView) {
super(itemView);
stationArtwork = itemView.findViewById(R.id.favicon);
stationName = itemView.findViewById(R.id.text);
stationPlayButton = itemView.findViewById(R.id.play_button);
equalizerView = itemView.findViewById(R.id.equalizer_view);
itemView.setOnClickListener(this);
stationPlayButton.setOnClickListener(this);
selectedItem = getAdapterPosition();
}
#Override
public void onClick(View v) {
int clickPosition = getAdapterPosition();
Log.d(TAG, "onClick: "+getAdapterPosition());
Log.d(TAG, "onClick: "+getLayoutPosition());
Log.d(TAG, "onClick: "+getItemId());
if(v == itemView) {
mOnClickListener.onListItemClick(clickPosition);
}else if(v == stationPlayButton)
{
mOnClickListener.onListItemPlay(clickPosition,stationPlayButton,equalizerView);
}
}
}
public interface ListItemClickListener {
void onListItemClick(int clickedItemIndex);
void onListItemPlay(int clickItemIndex,ImageButton i,EqualizerView eq);
}
}
These are ClickListeners in Main Activity
#Override
public void onListItemClick(int clickedItemIndex) {
if(mToast !=null)
{
mToast.cancel();
}
mToast = Toast.makeText(this,"Main Activity item clicked at position"+clickedItemIndex,Toast.LENGTH_SHORT);
mToast.show();
}
#Override
public void onListItemPlay(int clickItemIndex,ImageButton i , EqualizerView eq) {
i.setVisibility(View.GONE);
eq.setVisibility(View.VISIBLE);
eq.animateBars();
}
RecyclerView reuses ViewHolder instances. You need to invalidate ViewHolder state inside onBindViewHolder. In your case you should hide EqulizerView at least:
#Override
public void onBindViewHolder(#NonNull final StationViewHolder holder, int position) {
equalizerView.setVisibility(View.INVISIBLE);
....
}
Also, you should save which songs are playing to initialize ViewHolder state later.
More info at: https://developer.android.com/guide/topics/ui/layout/recyclerview#structure

How to call an Interstitial by clicking on an item in the list that goes through an Adapter?

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.

How to call scrollToPosition(position) inside recyclerView's adapter?

I have a setOnClick listener inside my onBindViewHolder
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
((ViewHolder) holder).txtType.setText(object.text);
((ViewHolder) holder).checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext, ""+position, Toast.LENGTH_SHORT).show();
//???.scrolltoPosition(position+1);
}
});
on click, I would be scrolling the viewport to the next recycler view item. I've done this inside my MainActivity java by recyclerView.scrollToPosition(position);. But inside Adapter Class on onBindViewHolder, I have no idea how to call my recyclerView on the Main Java Class.
How should I do this?
edit:
For simplification purposes, I revised this previous code, because I have used a multiview adapter for my recycler. Here is the multiview adapter:
public class MultiViewTypeAdapter extends RecyclerView.Adapter {
private ArrayList<InstructionModel>dataSet;
Context mContext;
int total_types;
private LinearLayoutManager manager;
public MultiViewTypeAdapter(LinearLayoutManager manager)
{
this.manager=manager;
}
public static class SimpleTextViewHolder extends RecyclerView.ViewHolder {
TextView txtType;
CardView cardView;
CheckBox checkBox;
public SimpleTextViewHolder(View itemView) {
super(itemView);
this.txtType = (TextView) itemView.findViewById(R.id.type);
this.cardView = (CardView) itemView.findViewById(R.id.card_view);
this.checkBox = (CheckBox) itemView.findViewById(R.id.checkBox);
}
}
public static class TimeTextViewHolder extends RecyclerView.ViewHolder {
TextView txtType;
CardView cardView;
CheckBox checkBox;
public TimeTextViewHolder(View itemView) {
super(itemView);
this.txtType = (TextView) itemView.findViewById(R.id.type);
this.cardView = (CardView) itemView.findViewById(R.id.card_view);
this.checkBox = (CheckBox) itemView.findViewById(R.id.checkBox);
}
}
public MultiViewTypeAdapter(ArrayList<InstructionModel> data, Context context) {
this.dataSet = data;
this.mContext = context;
total_types = dataSet.size();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case InstructionModel.SIMPLE_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.simple, parent, false);
return new SimpleTextViewHolder(view);
case InstructionModel.TIME_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.time, parent, false);
return new TimeTextViewHolder(view);
}
return null;
}
#Override
public int getItemViewType(int position) {
switch (dataSet.get(position).type) {
case 0:
return InstructionModel.SIMPLE_TYPE;
case 1:
return InstructionModel.TIME_TYPE;
default: return -1;
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int listPosition) {
InstructionModel object = dataSet.get(listPosition);
if (object != null) {
switch (object.type) {
case InstructionModel.SIMPLE_TYPE:
((SimpleTextViewHolder) holder).txtType.setText(object.text);
break;
case InstructionModel.TIME_TYPE:
((TimeTextViewHolder) holder).txtType.setText(object.text);
break;
}
}
}
#Override
public int getItemCount() {
return dataSet.size();
}
P.S.
If you see some random useless stuff, I was trying something.
Pass the LayoutManger with constuctor
class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
private LinearLayoutManager manager;
public Adapter(LinearLayoutManager manager)
{
this.manager=manager;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
((ViewHolder) holder).txtType.setText(object.text);
((ViewHolder) holder).checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext, ""+position, Toast.LENGTH_SHORT).show();
manager.scrollToPosition(position+1);
}
});
}
I think you should define a interface to notify your parent RecyclerView to do scroll operation, the RecyclerView into ViewHodler inside operation, resulting in the coupling
You can pass a listener object in the constructor which implements by Fragment OR Activity.
/**
* item click interface of adapter
*/
public interface MultiViewTypeAdapterListener {
void onScroll(int position)
}
This interface implements by Fragment OR Activity
/**
* On Scroll Implement Method from adapter listener.
*
* #param position
*/
#Override
public void onScroll(int position) {
// Here you can call that method
recyclerview.scrolltoPosition(position)
}
Then you pass this listener in the constructor of the adapter.
private void buildRecyclerView() {
multiViewTypeAdapter = new MultiViewTypeAdapter(this);
recyclerView.setAdapter(multiViewTypeAdapter);
}
In the constructor, you can assign like this
private MultiViewTypeAdapterListener mMultiViewTypeAdapterListener;
public OfferAdapter(MultiViewTypeAdapterListener mMultiViewTypeAdapterListener) {
this.mMultiViewTypeAdapterListener = mMultiViewTypeAdapterListener
}
}
Now you can use this listener by setting click listener on anyViwe like this
((ViewHolder) holder).checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext, ""+position, Toast.LENGTH_SHORT).show();
//???.scrolltoPosition(position+1);
mMultiViewTypeAdapterListener.onScroll(position+1);
}
});
It returns to call the method of onItemClick which implements this method.
private int getScrollRange() {
int scrollRange = 0;
if (parent.getChildCount() > 0) {
View child = parent.getChildAt(0);
scrollRange = Math.max(0,
child.getHeight() - (parent.getHeight()));
}
return scrollRange;
}
ScrollView parent=findViewById(R.id.scroll_Recipe_Detail);
parent.scrollTo(0,getScrollRange());
if you want to scroll on new items added, you must override "onItemsAdded".
Here is how I did it:
recyclerView.apply {
setHasFixedSize(true)
layoutManager = MyLinearLayoutManager(this#MainActivity)
...
}
private class MyLinearLayoutManager(private val context: Context) :
LinearLayoutManager(context) {
// Force new items appear at the top
override fun onItemsAdded(recyclerView: RecyclerView, positionStart: Int, itemCount: Int) {
super.onItemsAdded(recyclerView, positionStart, itemCount)
scrollToPosition(findLastVisibleItemPosition())
}
}

Launch another activity with cardview details

I want to throw Launch another activity with cardview details
this tutorial
http://androidbash.com/connecting-android-app-to-a-database-using-php-and-mysql/
public class MoviesAdapter extends RecyclerView.Adapter {
private Context context;
private List<Movie> movies;
public MoviesAdapter(Context context, List<Movie> movies) {
this.context = context;
this.movies = movies;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card,parent,false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.movieName.setText(movies.get(position).getMovieName());
holder.movieGenre.setText(movies.get(position).getMovieGenre());
Glide.with(context).load(movies.get(position).getImageLink()).into(holder.imageView);
}
#Override
public int getItemCount() {
return movies.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView movieName;
public TextView movieGenre;
public ImageView imageView;
public ViewHolder(View itemView) {
super(itemView);
movieName = (TextView) itemView.findViewById(R.id.moviename);
imageView = (ImageView) itemView.findViewById(R.id.image);
movieGenre = (TextView) itemView.findViewById(R.id.genre);
imageView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
showPopupMenu(v,position);
}
}
private void showPopupMenu(View view, int poaition) {
PopupMenu popup = new PopupMenu(context, view);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.menu_context, popup.getMenu());
popup.setOnMenuItemClickListener(new MenuClickListener(poaition));
popup.show();
}
class MenuClickListener implements PopupMenu.OnMenuItemClickListener {
Integer pos;
public MenuClickListener(int pos) {
this.pos=pos;
}
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.action_favourite:
Toast.makeText(context, movies.get(pos).getMovieName()+" is added to favourite", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_watch:
Toast.makeText(context, movies.get(pos).getMovieName()+" is added to watchlist", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_book:
Toast.makeText(context, "Booked Ticket for "+movies.get(pos).getMovieName(), Toast.LENGTH_SHORT).show();
return true;
default:
}
return false;
}
}
}
Must read: https://developer.android.com/training/basics/firstapp/starting-activity.html
When you click on a card take the data bound to this card and put it to the intent:
#Override
public void onClick(View v) {
int position = getAdapterPosition();
showPopupMenu(v,position);
Movie movie = movies.get(position);
Intent intent = new Intent(v.getContext(), MovieActivity.class);
intent.putExtraSerializable(MOVIE_KEY, movie);
v.getContext().startActivity(intent);
}
To make this work adjust your Movie class:
class Movie implements Serializable {// your fields and methods}
Then in MovieActivity onCreate:
Movie movie = (Movie) getIntent().getSerializableExtra(MOVIE_KEY);
Using this instance you can populate your view with a data.

Categories