问题
I have a RecyclerView
with data from local JSON
in CardView
. I need to implement on selected items when one or some item clicked(change background the item selected or highlight) (like edit in Line App ) but without Button or longpress
. But I don't want to use StateListDrawable
or (using XML) because I have some JSON
data which need to process later.
I need a state in my Activity like a boolean value or something to save every item which I clicked but I don't have any solution again. I have read and try some tutorial but it's not working. This is below my Activity now :
adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
@Override
public void OnRecyclerViewItemClicked(int position) {
boolean selectedItem = false;
adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
@Override
public void OnRecyclerViewItemClicked(int position) {
/* ------ boolean variabel for adapter but still not work ----- */
JSONObject filteredtableList= null;
try {
filteredtableList= new JSONObject("response").getJSONObject("tTisch");
}
catch (JSONException e) {
e.printStackTrace();
}
if (recyclerView == null) {
try {
filteredtableList.has("true");
filteredtableList.put(status, true);
} catch (JSONException e) {
e.printStackTrace();
}
}
else {
try {
filteredtableList.put(status, true);
}
catch (JSONException e) {
e.printStackTrace();
}
}
adapter.updateData(filteredTableList);
//----------------------------------------------------
try {
Toast.makeText(TableActivity.this, filteredTableList.getJSONObject(position).getString("tischnr"), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Adapter.java
public int lastCheckedPosition = -1;
.........
.........
.........
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position == lastCheckedPosition) {
holder.itemView.setBackgroundResource(R.color.colorRedTableOcc);
} else {
holder.itemView.setBackgroundResource(R.color.colorTableGreen);
}
try {
currItem = list.getJSONObject(position);
holder.txt_no_table.setText(currItem.getString("tischnr"));
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public int getItemCount() {
return list.length();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txt_no_table;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
}
@Override
public void onClick(View itemView) {
recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition());
lastCheckedPosition = getAdapterPosition();
notifyItemRangeChanged(0,list.length());
}
}
JSON.json
..............
"t-tisch": [
{
"tischnr": 1,
"departement": 1,
"normalbeleg": 0,
"kellner-nr": 0,
"bezeich": "TABLE 01",
"roomcharge": false,
"betriebsnr": 0
},
{
"tischnr": 2,
"departement": 1,
"normalbeleg": 0,
"kellner-nr": 0,
"bezeich": "TABLE 02",
"roomcharge": false,
"betriebsnr": 0
},
............
This is my Activity looks like
Update
Output now:
It's now highlight when I click the item (Thanks to @Burhanuddin Rashid) but its still half for my case. I only can select one item (I can't selected multiple/more items). I need to unselect again when I click the highlight item.
EDITED : I try to write new object and key in my JSON (JSON code above). In my logic, it will make a flag for every item is selected or not, but it still not work.
EDITED : this is my log error :
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.development_laptop.vhp_restotemp, PID: 3590
java.lang.NullPointerException: Attempt to invoke virtual method 'org.json.JSONObject org.json.JSONObject.put(java.lang.String, boolean)' on a null object reference
at com.example.development_laptop.vhp_restotemp.TableActivity$1.OnRecyclerViewItemClicked(TableActivity.java:74)
at com.example.development_laptop.vhp_restotemp.com.example.development_laptop.vhp_restotemp.recyclerview.source.Adapter$ViewHolder.onClick(Adapter.java:97)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
回答1:
You can apply setOnClickListener like this:-
View itemView;
Context context;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
this.context=parent.getContext();
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
holder.linearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorAccent,null));
}
else {
holder.linearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
}
}
});
}
回答2:
Try this:
onBindViewHolder:
if (position == lastCheckedPosition) {
holder.itemView.setBackgroundResource(R.drawable.ic_item_selection_background);
} else {
holder.itemView.setBackgroundResource(R.drawable.ic_item_deselection_background));
}
And this on ViewHolder:
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lastCheckedPosition = getAdapterPosition();
notifyItemRangeChanged(0,getItemCount());
}
});
Create lastCheckedPosition
as global variable
回答3:
Follow Below Code :
Put this code in your onBindViewHolder()
Method.
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final DataModel dataModel = arraylist.get(position);
final boolean isSelected = dataModel.isSelected();
if (isSelected) {
llParentLayout.setBackgroundColor(Color.Black);
} else {
llParentLayout.setBackgroundColor(Color.Green);
}
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txt_no_table;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty);
}
@Override
public void onClick(View itemView) {
final DataModel dataModel = arraylist.get(getAdapterPosition());
recyclerViewItemClickedListener.OnRecyclerViewItemClicked(dataModel);
}
}
In your Activity :
adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() {
@Override
public void OnRecyclerViewItemClicked(DataModel dataModel) {
dataModel.setSelected(!dataModel.isSelected());
adapter.notifyDataSetChanged();
}
});
回答4:
I totally change my code but its now work powerfully, here my code looks like :
I change my
Adapter
into generic adapter. Its not process any data, but its throw to my activity.public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> { public int lastCheckedPosition = -1; private static OnRecyclerViewItemClickedListener recyclerViewItemClickedListener; public void setOnRecyclerViewClickedListener (OnRecyclerViewItemClickedListener l) { recyclerViewItemClickedListener = l; } public interface OnRecyclerViewItemClickedListener { void OnRecyclerViewItemClicked(int position); void OnRecyclerViewItemBind(ViewHolder holder, int position); int OnRecyclerViewItemCount(); } public Adapter() { super(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item_empty, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { recyclerViewItemClickedListener.OnRecyclerViewItemBind(holder,position); } @Override public int getItemCount() { return recyclerViewItemClickedListener.OnRecyclerViewItemCount(); } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView txt_no_table; public ViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); txt_no_table = (TextView) itemView.findViewById(R.id.txt_no_table_empty); } @Override public void onClick(View itemView) { recyclerViewItemClickedListener.OnRecyclerViewItemClicked(getAdapterPosition()); } } }
And My
Activity
become like this :/*Add Click Listener*/ adapter.setOnRecyclerViewClickedListener(new Adapter.OnRecyclerViewItemClickedListener() { @Override public void OnRecyclerViewItemClicked(int position) { try { JSONObject currTable = filteredTableList.getJSONObject(position); if (currTable.has("selected")) { currTable.put("selected", !currTable.getBoolean("selected")); } else { currTable.put("selected",true); } adapter.notifyItemChanged(position); } catch (JSONException e) { e.printStackTrace(); } try { Toast.makeText(TableActivity.this, filteredTableList.getJSONObject(position).getString("tischnr"), Toast.LENGTH_SHORT).show(); } catch (JSONException e) { e.printStackTrace(); } } @Override public void OnRecyclerViewItemBind(Adapter.ViewHolder holder, int position) { try { JSONObject currTable = filteredTableList.getJSONObject(position); holder.txt_no_table.setText(currTable.getString("tischnr")); int queasy33Index = ProgramMethod.getJSONArrayIndex(queasy33List,"number2", currTable.getInt("tischnr")); if (queasy33Index >= 0) { holder.txt_no_table.setText(holder.txt_no_table.getText() + "-" + queasy33List.getJSONObject(queasy33Index).getString("key")); } if (currTable.has("selected") && currTable.getBoolean("selected")) { holder.itemView.setBackgroundResource(R.color.colorRedTableOcc); } else { holder.itemView.setBackgroundResource(R.color.colorTableGreen); } } catch (JSONException e) { e.printStackTrace(); } }
Now the click listener save any state and save into boolean value in my JSON file like below :
Thanks to everyone with suggest and great answer :)
回答5:
Try below code
Inside
public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
Put
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false);
v.setOnClickListener(new MyOnClickListener());
And create this class anywhere you want it
class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
int itemPosition = recyclerView.indexOfChild(v);
Log.e("Clicked and Position is ",String.valueOf(itemPosition));
}
}
I've read before that there is a better way but I like this way is easy and not complicated.
回答6:
All Above are very good answer but i am sure you will choose this one this gives you more flexibility than others
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new SideMenuClickListener() {
@Override
public void onClick(View view, int position) {
}
@Override
public void onLongClick(View view, int position) {
}
}));
static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private SideMenuClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final SideMenuClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean b) {
}
}
来源:https://stackoverflow.com/questions/41235278/multiple-selected-items-recyclerview-in-activity-java