i would like to print a toast when i click on a recyclerview, i have an error in the variable "context" in the OnClick Method, i dont find how to fix this error.
private class MyOnClickListener implements View.OnClickListener{
#Override
public void onClick(View view) {
int itemPosition = recyclerView.getChildLayoutPosition(view);
String item = items.get(itemPosition);
Toast.makeText(context, item, Toast.LENGTH_LONG).show();
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// get inflater and get view by resource id itemLayout
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
// return ViewHolder with View
v.setOnClickListener(mOnClickListener);
return new ViewHolder(v);
}
/**
* Get the size of items in adapter
* #return the size of items in adapter
*/
#Override
public int getItemCount() {
return items.size();
}
/**
* Bind View Holder with Items
* #param holder: the view holder
* #param position : the current position
*/
Change it as follows
Toast.makeText(view.getContext(), item, Toast.LENGTH_LONG).show();
Related
I have a recycler view with 11-row data items. I need to fix two spinners in each row. That the second spinner data should be dependent on the first Spinner data changes. While I'm making new entry data loaded correctly. When I came to edit the first spinner data loading correctly done and already existing data was fixed correctly. But in the second spinner, it shows the data of the last loaded item. i.e. Last row (11th row) spinner data has been set in all the second spinners. How to solve this?
Shown below code is under onBindViewHolder() method in recyclerViewAdapter
fortnightLookupList = gCache.getFortNightLookup();
for(int i = 0; i<fortnightLookupList.size(); i++){
funtioningSpinnerList.add(fortnightLookupList.get(i).getFunctioning());
}
reasoningAdapter =
new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, funtioningSpinnerList);
reasoningAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.functioningSpinner.setAdapter(reasoningAdapter);
if (entryStatus.equals(Constants.NEW)) {
holder.functioningSpinner.setOnItemSelectedListener(new AdapterView . OnItemSelectedListener () {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (pos > 0) {
remoteLocationEntryModelData.get(position).checkList =
funtioningSpinnerList.get(pos);
//loadScoreSpinner(funtioningSpinnerList.get(pos), holder, position);
scoreList.clear();
for (int i = 0; i < fortnightLookupList.size(); i++) {
if (fortnightLookupList.get(i).getFunctioning().equals(funtioningSpinnerList.get(pos)) ) {
scoreList.add(fortnightLookupList.get(i).getScore());
}
}
scoreAdapter =
new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.scoreSpinner.setAdapter(scoreAdapter);
} else {
remoteLocationEntryModelData.get(position).checkList = "$";
scoreList.clear();
scoreList.add(0, "---- select ----");
scoreAdapter =
new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.scoreSpinner.setAdapter(scoreAdapter);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
} else if (entryStatus.equals(Constants.EDIT)) {
if (!TextUtils.isEmpty( String.valueOf( editList.getDescriptions().get(position).getLogId() ) ) ) {
remoteLocationEntryModelData.get(position).logId =
editList.getDescriptions().get(position).getLogId();
}
if (!TextUtils.isEmpty(editList.getDescriptions().get(position).getRemarks())) {
holder.remarksEdt.setText(editList.getDescriptions().get(position).getRemarks());
}
holder.functioningSpinner.setSelection(
funtioningSpinnerList.indexOf(
editList.getDescriptions().get(position).getCheckList()
)
);
holder.functioningSpinner.setOnItemSelectedListener(new AdapterView . OnItemSelectedListener () {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (pos > 0) {
remoteLocationEntryModelData.get(position).checkList =
funtioningSpinnerList.get(pos);
//loadScoreSpinner(funtioningSpinnerList.get(pos), holder, position);
scoreList.clear();
for (int i = 0; i < fortnightLookupList.size(); i++) {
if (fortnightLookupList.get(i).getFunctioning()
.equals(funtioningSpinnerList.get(pos))
) {
scoreList.add(fortnightLookupList.get(i).getScore());
}
}
scoreAdapter =
new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.scoreSpinner.setAdapter(scoreAdapter);
//holder.scoreSpinner.setSelection(scoreList.indexOf(editList.getDescriptions().get(position).getScore()));
} else {
remoteLocationEntryModelData.get(position).checkList = "$";
scoreList.clear();
scoreList.add(0, "---- select ----");
scoreAdapter =
new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList);
scoreAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
holder.scoreSpinner.setAdapter(scoreAdapter);
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Note While I debug it step by step it is working correctly, but not when during run
Current Output
Expected Output
You save scoreList in a global variable and never redefines this value
In holder.functioningSpinner.setOnItemSelectedListener you makes scoreList.clear()
with always same line you set same List reference to all adapters in new ArrayAdapter<>(thisActivity, android.R.layout.simple_spinner_item, scoreList)
with scoreList.clear() you removes data in all adapters and adds new values.
=> is the reason, why you see the data of last item in all list items
Note While I debug it step by step it is working correctly, but not
when during run
Reason for it is:
in debug mode you are slow. there everything comes step by step.
in real execution everything happens in some milliseconds
HOW TO SOLVE
Possibility 1. recreate the list instead of clear data. You make already always new ArrayAdapter, why you store scoreList instance globally?
Possibility 2. Make a holder as own class and everything you do in onBindViewHolder make in a holder class.
Example:
generate base holder class
public abstract class BaseRecyclerBindingHolder<Item> extends RecyclerView.ViewHolder {
public BaseRecyclerBindingHolder(View itemView) {
super(itemView);
}
public abstract void configureView(Item item);
}
and base adapter class
public abstract class BaseRecyclerBindingAdapter<Item, Holder extends BaseRecyclerBindingHolder<? super Item>, ItemBinding extends ViewBinding>
extends RecyclerView.Adapter<Holder> {
// Store a member variable for the items
protected final List<Item> mItems;
/**
* #param items adapter items to show in UI
*/
public BaseRecyclerBindingAdapter(List<Item> items) {
mItems = items;
}
/**
* Usually involves inflating a layout from XML and returning the holder
*
* #param parent container of adapter items
* #param viewType type of item
* #return ViewHolder for adapter item
*/
#NonNull
#Override
public Holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Inflate the custom layout
ItemBinding itemView = getLayoutResource(LayoutInflater.from(parent.getContext()), parent);
return getHolder(itemView, viewType);
}
/**
* Involves populating data into the item through holder
*
* #param holder ViewHolder class to construct UI for item
* #param position item position in adapter
*/
#Override
public void onBindViewHolder(#NonNull Holder holder, int position) {
Item item = mItems.get(position);
holder.configureView(item);
}
/**
* #return count of items in adapter
*/
#Override
public int getItemCount() {
return mItems.size();
}
/**
* gets the type of item of specified position in adapter
*
* #param position item position
* #return default 0
*/
#Override
public abstract int getItemViewType(int position);
/**
* Usually use:
* ItemBinding.inflate(layoutInflater);
* To use parents properties of width and height, make this way:
* ItemBinding.inflate(layoutInflater, parent, false);
*
* #param layoutInflater the inflater to set XMl to view
* #param parent container of adapter items
* #return ViewBinding element with access to all views with IDs in UI
*/
protected abstract ItemBinding getLayoutResource(LayoutInflater layoutInflater, ViewGroup parent);
/**
* based on viewType gets the ViewHolder class for the item
*
* #param viewBinding element with access to all views with IDs in UI
* #param viewType type of item
* #return ViewHolder for adapter item
*/
protected abstract Holder getHolder(ItemBinding viewBinding, int viewType);
/**
* #param position item position
* #return item on specified position in adapter
*/
public Item getItem(int position) {
return mItems.get(position);
}
/**
* #return list of items in adapter
*/
public List<Item> getItems() {
return mItems;
}
}
now generate specific holder for your purpose
public class YourHolderName extends BaseRecyclerBindingHolder<YourHolderItem> {
private final YourHolderBinding binding;
// add here more variable that you needs from adapter
public YourHolderName(YourHolderBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
#Override
public void configureView(YourHolderItem yourHolderItem) {
// here comes what you make i your holder
}
}
and at least define adapter that is always super easy and small
public class YourAdapterName extends BaseRecyclerBindingAdapter<YourHolderItem, YourHolderName, YourHolderBinding> {
/**
* #param yourHolderItem adapter items to show in UI
*/
// add more parameters if needed
public YourAdapterName(List<YourHolderItem> yourHolderItems) {
super(yourHolderItems);
}
#Override
public int getItemViewType(int position) {
return 0;
}
#Override
protected YourHolderBinding getLayoutResource(LayoutInflater layoutInflater, ViewGroup parent) {
return YourHolderBinding.inflate(layoutInflater, parent, false);
}
#Override
protected YourHolderName getHolder(YourHolderBinding viewBinding, int viewType) {
// add more parameters if needed
return new YourHolderName(viewBinding);
}
}
I have a PopupWindow that contains a RecyclerView. The RecyclerView's last element is a button that adds a new item to the end of the adapter's list when clicked.
The problem:
During the first time my PopupWindow has been launched the button successfully adds new items to the RecyclerView with notifyItemInserted(dataSize - 1) when clicked, but the RecyclerView doesn't update and show them. If I close and re-open the PopupWindow however, the items previously added are properly shown in the RecyclerView and it properly updates and animates new items being added to its adapter.
The Question: I'm not sure why the RecyclerView doesn't refresh and show the newly added items on first run of the PopupWindow, but works perfectly from second run onward. How do I make it work during the first run of the PopupWindow?
P.S. Its worth noting that if I use notifyDataSetChanged() the RecyclerView works correctly (displays new items) even on first launch of the PopupWindow. I want to find a way to make notifyItemInserted() work however, because it has nice animations when new items are added.
UserChordsAdapter.java
public class UserChordsAdapter extends RecyclerView.Adapter<UserChordsAdapter.ChordViewHolder> {
private Context context;
private final ListItemClickListener mClickHandler;
private ArrayList<String> mChordData = new ArrayList<String>(); //contains all user created chords as comma delimited note #s
/**
* The interface that receives onClick messages.
*/
public interface ListItemClickListener {
void onListItemClick(int clickedItemIndex);
}
/**
*
* #param clickHandler The on-click handler for this adapter. This single handler is called
* when an item is clicked.
*/
public UserChordsAdapter(ListItemClickListener clickHandler) {
mClickHandler = clickHandler;
}
#Override
public ChordViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
int layoutIdForListItem = R.layout.user_chord_list_item;
int layoutIdForFooterItem = R.layout.user_chord_add_new;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View listItem;
ChordViewHolder viewHolder;
if (viewType == R.layout.user_chord_list_item) { //inflate chord item
listItem = inflater.inflate(layoutIdForListItem, parent, shouldAttachToParentImmediately);
viewHolder = new ChordViewHolder(listItem);
}
else { //inflate "+ Add new" button (last list item)
listItem = inflater.inflate(layoutIdForFooterItem, parent, shouldAttachToParentImmediately);
viewHolder = new ChordViewHolder(listItem);
}
return viewHolder;
}
#Override
public void onBindViewHolder(ChordViewHolder holder, int position) {
if (position == mChordData.size()){
holder.mAddChordButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mChordData.add("1,30,40");
notifyItemInserted(mChordData.size()-1);
}
});
}
else {
holder.mChordName.setText("Chord " + Integer.toString(position));
}
}
#Override
public int getItemCount() {
if (mChordData == null){
return 1;
}
return mChordData.size() + 1; // +1 is for footer button (add new)
}
class ChordViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
// Will display which ViewHolder is displaying this data
TextView mChordName;
Button mAddChordButton;
/**
* Constructor for our ViewHolder. Within this constructor, we get a reference to our
* TextViews and set an onClickListener to listen for clicks. Those will be handled in the
* onClick method below.
*/
public ChordViewHolder(View itemView) {
super(itemView);
mAddChordButton = (Button) itemView.findViewById(R.id.button_add_new);
mChordName = (TextView) itemView.findViewById(R.id.tv_view_holder_instance);
itemView.setOnClickListener(this);
}
/**
* Called whenever a user clicks on an item in the list.
* #param v The View that was clicked
*/
#Override
public void onClick(View v) {
int clickedPosition = getAdapterPosition();
String chordData = mChordData.get(clickedPosition);
mClickHandler.onListItemClick(clickedPosition);
}
}
/**
* Distinguishes if view is a Chord list item or the last item in the list (add new chord)
* #param position
* #return
*/
#Override
public int getItemViewType(int position) {
return (position == mChordData.size()) ? R.layout.user_chord_add_new : R.layout.user_chord_list_item;
}}
FragmentChordMenu.java
public class FragmentChordMenu extends Fragment implements UserChordsAdapter.ListItemClickListener{
private FloatingActionButton mFAB;
private View mPopupView;
private PopupWindow mUserChordMenu;
private RecyclerView mUserChordsList;
private UserChordsAdapter mRecyclerViewAdapter;
private int numItems = 0; //TODO: dynamically calculate this as # of saved chords + 1(add new)
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerViewAdapter = new UserChordsAdapter(this);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.menu_fragment_chord, container, false);
LayoutInflater layoutInflater = (LayoutInflater)getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mPopupView = layoutInflater.inflate(R.layout.menu_popup_set_chords, null);
int menuWidth = (int)(MainActivity.getActualWidth()*.95);
int menuHeight = (int)(MainActivity.getActualHeight()*.90);
mUserChordMenu = new PopupWindow(mPopupView, menuWidth, menuHeight);
mUserChordMenu.setFocusable(true);
mFAB = (FloatingActionButton) v.findViewById(R.id.addChord);
mFAB.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mUserChordMenu.showAtLocation(mPopupView, Gravity.CENTER, 10, 10);
mUserChordsList = (RecyclerView) mPopupView.findViewById(R.id.rv_userChords);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
mUserChordsList.setLayoutManager(layoutManager);
mUserChordsList.setAdapter(mRecyclerViewAdapter);
}
});
return v;
}
/**
* Called from UserChordsAdapter's onClick. Only fires on list item clicks, not the add new button
*
* */
#Override
public void onListItemClick(int clickedItemIndex) {
}}
The problem lies with the logic you use to update your views. Currently what you are saying is this, only notify my data when a view is drawn on the screen(OnBind). That is why it always work for the second try, because whenever a view is being drawn(swipe etc). that onBind method will be triggered.What you need to do is to create a method in the Adapter class, that replaces this logic.
holder.mAddChordButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
mChordData.add("1,30,40");
notifyItemInserted(mChordData.size()-1);
}
});
So create a method that adds item to the mChorData set object, then call notifyItemInserted(mChordData.size()-1); in that method. This will always update and notify the adapter of any changes, hence triggering redraw automatically.
First create a public method in UserChordsAdapter that accepts an mChordData for its paramter,then in that method call, notifyItemInserted(mChordData.size()-1);. Firstly you need to expose the clickListener outside of that adapter.
I'm trying to do AlertDialog with custom list (image + text). I'm using custom adapter, it works, but I don't understand why the onClick event does not work.
I had already tried create ListView, set my adapter to it and than set view to my AlertDialog, but I still can not catch the event. What am I doing wrong?
ArrayList<ItemData> list = ItemData.createFromMaterialArray(materials);
MaterialsAdapter adapter = new MaterialsAdapter(this,
R.layout.custom_material_item, R.id.text, list);
AlertDialog.Builder materialTypesDialog = new AlertDialog.Builder(this);
materialTypesDialog.setTitle(R.string.material);
materialTypesDialog.setAdapter(adapter, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// Nothing happens, why???
Toast.makeText(context, "WORK", Toast.LENGTH_LONG).show();
}
});
materialTypesDialog.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Same problem
Toast.makeText(context, "WORK", Toast.LENGTH_LONG).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
materialTypesDialog.show();
My adapter, i used similar adapter for spinners and it works fine.
class MaterialsAdapter extends ArrayAdapter<ItemData> {
private int groupId;
Activity context;
ArrayList<ItemData> list;
private LayoutInflater inflater;
/**
* #param context
* #param _groupId
* #param _id
* #param list
*/
MaterialsAdapter(Activity context, int _groupId, int _id, ArrayList<ItemData>
list) {
super(context, _id, list);
this.list = list;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.groupId = _groupId;
}
/**
* #param position
* #param convertView
* #param parent
* #return
*/
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = inflater.inflate(groupId, parent, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.image);
imageView.setImageResource(list.get(position).getImageId());
TextView textView = (TextView) itemView.findViewById(R.id.text);
textView.setText(list.get(position).getTextId());
return itemView;
}
/**
* #param position
* #param convertView
* #param parent
* #return
*/
public View getDropDownView(int position, View convertView, ViewGroup
parent) {
return getView(position, convertView, parent);
}
}
ItemData class
class ItemData {
private String id;
private int textId;
private int imageId;
/**
* #param id
* #param textId
* #param imageId
*/
private ItemData(String id, int textId, int imageId) {
this.id = id;
this.textId = textId;
this.imageId = imageId;
}
/**
* #return
*/
int getTextId() {
return textId;
}
/**
* #return
*/
int getImageId() {
return imageId;
}
/**
* #return
*/
String getId() {
return id;
}
/**
* #return
*/
static ArrayList<ItemData> createFromMaterialArray(Material[] materials) {
ArrayList<ItemData> itemDataList = new ArrayList<>();
for (Material material : materials) {
itemDataList.add(
new ItemData(material.getName(),
material.textID,
material.imageID);
}
return itemDataList;
}}
Layout custom_material_item looks like simple LineralLayout with two items(TextView and ImageView).
The problem was in my custom item Layout. In my parent LineralLayout was added Clickable="true", thats why OnClickListner didn't triggered.
Try to get ListView from your alertdialog and setOnItemClickListener like below:
materialTypesDialog.getListView().setOnItemClickListener(
new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
Or
Need to add below code to create and show alertDialog:
AlertDialog mAlertDialog = materialTypesDialog.create();
mAlertDialog.show();
And remove setOnItemSelectedListener. It is not working with AlertDialog.
I'm making an application were i show a list of cardviews using a recyclerview and i want to be able to make a detail activity of the cardview the user clicks but i dont know how to send the item that is clicked to the next activity.
Here u can see my adapter:
/**
* Created by alberto on 18/05/16.
*/
public class EmpresasAdapter extends RecyclerView.Adapter<EmpresasAdapter.EmpresasViewHolder>
implements ItemClickListener{
private final Context context;
private List<Empresas> items;
public EmpresasAdapter(Context context, List<Empresas> items) {
this.context = context;
this.items = items;
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public EmpresasViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.empresa_card, viewGroup, false);
return new EmpresasViewHolder(v, this);
}
#Override
public void onBindViewHolder(EmpresasViewHolder viewHolder, int i) {
// Item procesado actualmente
Empresas currentItem = items.get(i);
viewHolder.nombrep.setText(currentItem.getNombre());
viewHolder.descripcionp.setText(currentItem.getDescripcionC());
viewHolder.franquiciap.setText(currentItem.getModalidad()+" | "+currentItem.getFranquicia());
// Cargar imagen
Glide.with(context)
.load(currentItem.getImagen())
.into(viewHolder.imagenp);
}
#Override
public void onItemClick(View view, int position) {
// Imagen a compartir entre transiciones
View sharedImage = view.findViewById(R.id.imagenp);
EmpresaDetalle.launch(
(Activity) context, position, sharedImage);
}
/**
* View holder para reciclar elementos
*/
public static class EmpresasViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
// Views para un curso
public ImageView imagenp;
public TextView nombrep;
public TextView descripcionp;
public TextView franquiciap;
// Interfaz de comunicaciĆ³n
public ItemClickListener listener;
public EmpresasViewHolder(View v, ItemClickListener listener) {
super(v);
nombrep = (TextView) v.findViewById(R.id.nombrep);
descripcionp = (TextView) v.findViewById(R.id.descripcionp);
franquiciap = (TextView) v.findViewById(R.id.Franquiciap);
imagenp = (ImageView) v.findViewById(R.id.imagenp);
v.setOnClickListener(this);
this.listener = listener;
}
#Override
public void onClick(View v) {
listener.onItemClick(v, getAdapterPosition());
}
}
Put the items as extra to the intent for launching the DetailedActivty:
#Override
public void onItemClick(View view, int position) {
// Imagen a compartir entre transiciones
View sharedImage = view.findViewById(R.id.imagenp);
Intent intent = new Intent(context, DetailedActivty.class)
intent.putExtra(nombrep, NOMBREP_EXTRA);
intent.putExtra(descripcionp, DESCRIPCIONP_EXTRA);
intent.putExtra(franquiciap, FRANQUICIAP_EXTRA);
context.startActivity(intent);
}
Change your onCreateViewHolder like this
public EmpresasViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.empresa_card, viewGroup, false);
v.setOnClickListener(new View.OnClickListener{
#Override
public void onClick(View v){
//you have the cardView in v;
//you can access the child view of your cardView by referring to v
//if you want to get the position you can do it here.
//Create an intent with the collected data an d start the activity
}
});
return new EmpresasViewHolder(v, this);
}
You can do this in onBindView() method too. Position is easily accessible with this method. But that does not mean that you can't have the position in the former method. You can. But I've not described it. Will do if you want.
//to do this its easier if you have assigned and id to the cardView in XML and store the cardView in the viewHOlder
//getting cardView
CardView cardView=holder.cardView;
cardView.setOnClickListener(new View.OnClickListener{
#Override
public void onClick(View v){
//position is easily availble now.
//you can access the rest of the views
//create youtr intent and start the activity
}
});
I am trying to change the color of the view when it's selected in RecyclerView.
I used the adapter from this tutorial: http://www.android4devs.com/2014/12/how-to-make-material-design-navigation-drawer.html and add the onClick method from the answer: https://stackoverflow.com/a/27868923/3569225.
This is my code now:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private static final int TYPE_HEADER = 0; // Declaring Variable to Understand which View is being worked on
// IF the view under inflation and population is header or Item
private static final int TYPE_ITEM = 1;
private String mNavTitles[]; // String Array to store the passed titles Value from MainActivity.java
private int mIcons[]; // Int Array to store the passed icons resource value from MainActivity.java
private String name; //String Resource for header View Name
private int mSelectedPosition = 0;
private OnMyListItemClick mOnMainMenuClickListener = OnMyListItemClick.NULL;
// Creating a ViewHolder which extends the RecyclerView View Holder
// ViewHolder are used to to store the inflated views in order to recycle them
public static class ViewHolder extends RecyclerView.ViewHolder {
int Holderid;
TextView textView;
ImageView imageView;
TextView Name;
public ViewHolder(View itemView,int ViewType) { // Creating ViewHolder Constructor with View and viewType As a parameter
super(itemView);
// Here we set the appropriate view in accordance with the the view type as passed when the holder object is created
if(ViewType == TYPE_ITEM) {
textView = (TextView) itemView.findViewById(R.id.rowText); // Creating TextView object with the id of textView from item_row.xml
imageView = (ImageView) itemView.findViewById(R.id.rowIcon);// Creating ImageView object with the id of ImageView from item_row.xml
Holderid = 1; // setting holder id as 1 as the object being populated are of type item row
}
else{
Name = (TextView) itemView.findViewById(R.id.name); // Creating Text View object from header.xml for name
Holderid = 0; // Setting holder id = 0 as the object being populated are of type header view
}
}
}
public interface OnMyListItemClick {
OnMyListItemClick NULL = new OnMyListItemClick() {
#Override
public void onMyListItemClick(View itemView) {
}
};
void onMyListItemClick(View itemView);
}
MyAdapter(String Titles[],int Icons[],String Name){ // MyAdapter Constructor with titles and icons parameter
// titles, icons, name, email, profile pic are passed from the main activity as we
mNavTitles = Titles; //have seen earlier
mIcons = Icons;
name = Name;
//in adapter
}
//Below first we ovverride the method onCreateViewHolder which is called when the ViewHolder is
//Created, In this method we inflate the item_row.xml layout if the viewType is Type_ITEM or else we inflate header.xml
// if the viewType is TYPE_HEADER
// and pass it to the view holder
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_list_item,parent,false); //Inflating the layout
final ViewHolder vhItem = new ViewHolder(v,viewType); //Creating ViewHolder and passing the object of type view
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//here you set your current position from holder of clicked view
mSelectedPosition = ((ViewHolder) view.getTag()).getPosition();
//here you pass object from your list - item value which you clicked
//OnMainMenuClickListener.onMyListItemClick(yourObjectList.get(mSelectedPosition));
//here you inform view that something was change - view will be invalidated
notifyDataSetChanged();
}
});
return vhItem; // Returning the created object
} else if (viewType == TYPE_HEADER) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.drawer_header,parent,false); //Inflating the layout
ViewHolder vhHeader = new ViewHolder(v,viewType); //Creating ViewHolder and passing the object of type view
return vhHeader; //returning the object created
}
return null;
}
//Next we override a method which is called when the item in a row is needed to be displayed, here the int position
// Tells us item at which position is being constructed to be displayed and the holder id of the holder object tell us
// which view type is being created 1 for item row
#Override
public void onBindViewHolder(MyAdapter.ViewHolder holder, int position) {
if(holder.Holderid ==1) { // as the list view is going to be called after the header view so we decrement the
// position by 1 and pass it to the holder while setting the text and image
holder.textView.setText(mNavTitles[position - 1]); // Setting the Text with the array of our Titles
holder.imageView.setImageResource(mIcons[position -1]);// Settimg the image with array of our icons
if(mSelectedPosition == position)
holder.itemView.setBackgroundColor(Color.CYAN);
else
holder.itemView.setBackgroundColor(Color.RED);
}
else{
holder.Name.setText(name);
}
}
// you can create your own listener which you set for adapter
public void setOnMainMenuClickListener(OnMyListItemClick onMyListItemClick) {
mOnMainMenuClickListener = onMyListItemClick == null ? OnMyListItemClick.NULL : onMyListItemClick;
}
// This method returns the number of items present in the list
#Override
public int getItemCount() {
return mNavTitles.length+1; // the number of items in the list will be +1 the titles including the header view.
}
// Witht the following method we check what type of view is being passed
#Override
public int getItemViewType(int position) {
if (isPositionHeader(position))
return TYPE_HEADER;
return TYPE_ITEM;
}
private boolean isPositionHeader(int position) {
return position == 0;
}
}
But when I am clicking item, the app is crash and the error is :Attempt to invoke virtual method 'int com.*****.******.app.MyAdapter$ViewHolder.getPosition()' on a null object reference.
What did I do wrong?