I want to add, for each row in ListView, a checkbox which will be activated and shown on long press, I don't know whether I think correctly, I should add in row layout a Checkbox which is default hidden and when action start all check box on list will be shown and able to check?
To show CheckBox on each row:
1. Add an extra boolean variable isLongPressed to your adapter class and initialized with default false value from adapter constructor.
2. In your adapter getView()/ onBindViewHolder() method add an condition like this:
CheckBox checkBox = (CheckBox) view.findViewById(R.id.check);
if(isLongPressed)
{
checkBox.setVisibility(View.VISIBLE);
} else {
checkBox.setVisibility(View.GONE);
}
3. Add an method showCheckbox() to your adapter class to update ListView with checkbox visible state.
public void showCheckbox()
{
isLongPressed = true;
notifyDataSetChanged(); // Required for update
}
4. Call showCheckbox() from onItemLongClick:
list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MainActivity.this, "Long Click", Toast.LENGTH_SHORT).show();
your_adapter.showCheckbox();
return true;
}
});
Here is good tutorial about Contextual Action Mode
Hope this will help~
Try this:
We will use a recyclerview, and a checkbox adapter
Chechbox Adapter layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/checkbox_adapter_item_height"
android:gravity="center_vertical"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal">
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:theme="#style/MyCheckBoxTheme"
android:clickable="false"
android:longClickable="false"
android:focusable="false"/>
<TextView
android:id="#+id/tvItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="item1"
android:visibility="visible"
android:padding="6dp"
android:paddingStart="12dp"
android:textColor="#color/colorMaterialBlack"
android:textSize="16sp" />
</LinearLayout>
A style for checkbox, keep this in style
<style name="MyCheckBoxTheme" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">#color/colorBlackDimText</item>
<item name="colorControlActivated">#color/greenStatus</item>
</style>
A Model for the Checkbox adapter you can define/add/remove vars in your model
public class CheckboxTitlesData {
private String title;
private boolean isSelected;
public CheckboxTitlesData(String title, boolean isSelected) {
this.title = title;
this.isSelected = isSelected;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
}
Checkbox Adapter
public class CheckboxTitleAdapter extends RecyclerView.Adapter<CheckboxTitleAdapter.ViewHolder> implements GenericAdapterInterface{
List<CheckboxTitlesData> dataList = new ArrayList<>();
private CheckboxTitlesData previousSelection;
protected MyApplication.MenuSelectionListener listener;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(getRootLayout(), parent, false);
return new ViewHolder(view);
}
public CheckboxTitleAdapter(MyApplication.MenuSelectionListener listener){
this.listener = listener;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
CheckboxTitlesData data = dataList.get(position);
if (data.isSelected()){
previousSelection = data;
holder.checkBox.setChecked(true);
}else holder.checkBox.setChecked(false);
holder.tvItem.setText(data.getTitle());
}
#Override
public int getItemCount() {
return dataList.size();
}
#Override
public void changeData(List dataList) throws IllegalArgumentException{
if (dataList == null || dataList.size() <= 0)
return;
if (!(dataList.get(0) instanceof CheckboxTitlesData))
throw new IllegalArgumentException("Required data type \"CheckboxTitlesData\"");
this.dataList.clear();
this.dataList.addAll(dataList);
(new Handler(Looper.getMainLooper())).postDelayed(new Runnable() {
#Override
public void run() {
notifyDataSetChanged();
}
}, 100);
}
#Override
public int getRootLayout() {
return R.layout.adapter_title_checkbox;
}
#Override
public void setOnClickListener(RecyclerView.ViewHolder holder) {
holder.itemView.setOnLongClickListener((View.OnLongClickListener) holder);
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
#Bind(R.id.tvItem)
TextView tvItem;
#Bind(R.id.checkbox)
CheckBox checkBox;
ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setOnClickListener(this);
setOnClickListener(this);
}
#Override
public boolean onLongClick(View v) {
final int pos = dataList.indexOf(previousSelection);
if (pos == getAdapterPosition())
return;
if (listener != null)
listener.onMenuSelected(dataList.get(getAdapterPosition()));
CheckboxTitlesData data = dataList.get(getAdapterPosition());
data.setSelected(true);
dataList.set(getAdapterPosition(), data);
if (pos != -1) {
previousSelection.setSelected(false);
dataList.set(pos, previousSelection);
}
(new Handler(Looper.getMainLooper())).postDelayed(new Runnable() {
#Override
public void run() {
notifyDataSetChanged();
}
}, 100);
return true
}
}
}
Interface, u can remove the interface if you wanted, I just use this for my adapters usually for readability for other dev:
public interface GenericAdapterInterface {
void changeData(List dataList) throws Exception;
int getRootLayout();
void setOnClickListener(RecyclerView.ViewHolder holder);
}
Recycler view layout xml, add the recyclerview whr you need, this is just an eg
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llBody"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingEnd="#dimen/padding_normal"
android:paddingStart="#dimen/padding_normal">
<android.support.v7.widget.RecyclerView
android:id="#+id/rvMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Activity/fragment that uses the recycler view must do this
#Bind(R.id.rvMenu)
RecyclerView rvMenu;
private CheckboxTitleAdapter menuAdapter;
//Define an interface for callback on long press
public interface YourOwnInterface {
void onLonPress(Object data);
}
private void setUpRecycleView() {
RecyclerView.LayoutManager mLayoutManager = new
LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
rvMenu.setHasFixedSize(false);
rvMenu.setLayoutManager(mLayoutManager);
rvMenu.setItemAnimator(new DefaultItemAnimator());
YourOwnInterface listener = new YourOwnInterface () {
#Override
public void onLonPress(Object data) {
updateView((CheckboxTitlesData) data);
}
};
//this interface is needed wen a longpress is made adapter and the callback is given to your Acitivity/Fragment you can perform necessary opreation
menuAdapter = new CheckboxTitleAdapter(listener);
rvMenu.setAdapter(menuAdapter);
}
private void updateView(CheckboxTitlesData data) {
//perform operation on long press
}
Done it works
Related
I want to set OnClickListeners to the items from my Expandable Recycleview. Each item from the Recycleview should have a button ( like this https://imgur.com/qlEJCkk : a + button to add tasks and an "x" button for each task to delete it)
I have tried to implement it from some other examples of onClickListeners but nothing worked so far
this is the ADAPTER:
public class ExpandableAdapter extends ExpandableRecyclerViewAdapter<RoutineViewHolder, TaskViewHolder> {
public ExpandableAdapter(List<? extends ExpandableGroup> groups) {
super(groups);
}
#Override
public RoutineViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.expandable_recyclerview_routine, parent, false);
return new RoutineViewHolder(v);
}
#Override
public TaskViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.expandable_recyclerview_task, parent, false);
return new TaskViewHolder(v);
}
#Override
public void onBindChildViewHolder(TaskViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
final Tasks tasks = (Tasks) group.getItems().get(childIndex);
holder.bind(tasks);
}
#Override
public void onBindGroupViewHolder(RoutineViewHolder holder, int flatPosition, ExpandableGroup group) {
final Routine routine = (Routine) group;
holder.bind(routine);
}
RoutineViewHolder:
import com.thoughtbot.expandablerecyclerview.viewholders.GroupViewHolder;
public class RoutineViewHolder extends GroupViewHolder implements View.OnClickListener {
private TextView mTextView;
public RoutineViewHolder(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.exp_routine);
itemView.setOnClickListener(this);
}
public void bind(Routine routine){
mTextView.setText(routine.getTitle());
}
}
TaskViewHolder:
public class TaskViewHolder extends ChildViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
private Boolean checkVal;
public TaskViewHolder(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.exp_task);
mCheckBox=itemView.findViewById(R.id.exp_task_checkbox);
}
public void bind(Tasks tasks) {
mTextView.setText(tasks.name);
checkVal=((tasks.checkBox==1)?Boolean.TRUE:Boolean.FALSE);
mCheckBox.setChecked(checkVal);
}
}
as you can see I have 2 ViewHolders : RoutineViewHolder and TaskViewHolder. I am very confused to where and how I should set the OnClickListener since I want it to behave different for the "Routines" and "Tasks" because they would have different buttons.
"Tasks" should have the + button to add tasks underneath it
and each task should have an X button to delete that specific task
the expandable recycleview is made out of 2 more of these "Tasks" cathegories.
I would prefer a solution where I can listen all these callbacks from some higher level (like Activity) where I can change data objects and refresh the RecyclerView keep things in sync based on callbacks. (This is eventually what you will need if you scale this.)
I implemented your code and modified a little to get the expected result.
For this solution:
I created an interface to get callbacks
On Add clicked on Routine
On Delete clicked on Task
On check status changed on Task
Made my activity to implement that interface and passed it to adapter.
Adapter passes it to ViewHolder
ViewHolder will invoke required function upon click.
In call backs:
For ADD: You can know which Routine was clicked
For Delete: You can know ParentRoutine, Child Index of Task and Task
For Check Change: You can know ParentRoutine, Child Index of Task, Task and New check status.
Code
1. Add new file ListActionListener.java
This is the interface.
public interface ListActionListener {
// Know add was clicked on given routine
void onAddTaskClicked(Routine routine);
// Know delete was clicked on given task.
void onDeleteTaskClicked(Routine routine, Tasks task, int index);
// Know checkbox clicked on given task (with new checked status)
void onTaskCheckChanged(Routine routine, Tasks task, int index, boolean checked);
}
2. Make your activity implement this interface. ExpandableListActivity.java
This is my sample activity that you see in the screenshots.
public class ExpandableListActivity extends AppCompatActivity implements ListActionListener{
ExpandableAdapter adapter;
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_expandable_list);
recyclerView = findViewById(R.id.recyclerView);
loadList();
}
private void loadList() {
List<Routine> routines = getDummyRoutineList();
adapter = new ExpandableAdapter(routines, this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
private List<Routine> getDummyRoutineList() {
List<Routine> list = new ArrayList<Routine>();
Tasks rt1 = new Tasks("R1 Tasks1", 1);
Tasks rt2 = new Tasks("R1 Tasks2", 0);
Tasks rt3 = new Tasks("R1 Tasks3", 1);
Tasks rt4 = new Tasks("R1 Tasks4", 0);
Tasks rt5 = new Tasks("R1 Tasks5", 0);
List<Tasks> r1Tasks = new ArrayList<>();
r1Tasks.add(rt1);
r1Tasks.add(rt2);
r1Tasks.add(rt3);
r1Tasks.add(rt4);
r1Tasks.add(rt5);
Routine r1 = new Routine("Routine 1", r1Tasks);
Tasks r2t1 = new Tasks("R2 Tasks1", 1);
Tasks r2t2 = new Tasks("R2 Tasks2", 0);
Tasks r2t3 = new Tasks("R2 Tasks3", 1);
Tasks r2t4 = new Tasks("R2 Tasks4", 0);
Tasks r2t5 = new Tasks("R2 Tasks5", 1);
List<Tasks> r2Tasks = new ArrayList<>();
r2Tasks.add(r2t1);
r2Tasks.add(r2t2);
r2Tasks.add(r2t3);
r2Tasks.add(r2t4);
r2Tasks.add(r2t5);
Routine r2 = new Routine("Routine 2", r2Tasks);
list.add(r1);
list.add(r2);
return list;
}
#Override
public void onAddTaskClicked(Routine routine) {
Toast.makeText(this, "On Add Clicked", Toast.LENGTH_SHORT).show();
}
#Override
public void onDeleteTaskClicked(Routine routine, Tasks task, int index) {
Toast.makeText(this, "On Delete Clicked", Toast.LENGTH_SHORT).show();
}
#Override
public void onTaskCheckChanged(Routine routine, Tasks task, int index, boolean checked) {
Toast.makeText(this, "On Check changed:"+checked, Toast.LENGTH_SHORT).show();
}
}
3. Add "X" button to Task Row layout
This is my sample XML file, your XML may look different. Main thing is to add button for Delete.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp"
>
<Button
android:id="#+id/btn_delete"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="X"
/>
<CheckBox
android:id="#+id/exp_task_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
/>
<TextView
android:id="#+id/exp_task"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/btn_delete"
android:layout_toRightOf="#+id/exp_task_checkbox"
/>
</RelativeLayout>
4. Add "+" button to Routine Layout file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp"
>
<Button
android:id="#+id/btn_add"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="+"
/>
<TextView
android:id="#+id/exp_routine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/btn_delete"
android:layout_toRightOf="#+id/exp_task_checkbox"
/>
</RelativeLayout>
5. Update Adapter to accept a ListActionListener
public class ExpandableAdapter extends ExpandableRecyclerViewAdapter<RoutineViewHolder, TaskViewHolder> {
ListActionListener listActionListener;
public ExpandableAdapter(List<? extends ExpandableGroup> groups, ListActionListener listActionListener) {
super(groups);
this.listActionListener = listActionListener;
}
#Override
public RoutineViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.expandable_recyclerview_routine, parent, false);
return new RoutineViewHolder(v);
}
#Override
public TaskViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.expandable_recyclerview_task, parent, false);
return new TaskViewHolder(v);
}
#Override
public void onBindChildViewHolder(TaskViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
final Tasks tasks = (Tasks) group.getItems().get(childIndex);
holder.bind((Routine)group, childIndex, tasks, listActionListener);
}
#Override
public void onBindGroupViewHolder(RoutineViewHolder holder, int flatPosition, ExpandableGroup group) {
final Routine routine = (Routine) group;
holder.bind(routine, listActionListener);
}
}
6. Update TaskViewHolder.java
To accepte listener and invoke callback
public class TaskViewHolder extends ChildViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
private Boolean checkVal;
private Button btnDelete;
public TaskViewHolder(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.exp_task);
mCheckBox=itemView.findViewById(R.id.exp_task_checkbox);
btnDelete = itemView.findViewById(R.id.btn_delete);
}
public void bind(final Routine parentRoutine, final int childIndex, final Tasks tasks, final ListActionListener listActionListener) {
mTextView.setText(tasks.name);
checkVal=((tasks.checkBox==1)?Boolean.TRUE:Boolean.FALSE);
mCheckBox.setChecked(checkVal);
//add delete button click
btnDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listActionListener.onDeleteTaskClicked(parentRoutine, tasks, childIndex);
}
});
mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
//to avoid initial call back
if(checked != checkVal) {
listActionListener.onTaskCheckChanged(parentRoutine, tasks, childIndex, checked);
checkVal = checked;
}
}
});
}
}
7. Update RoutineViewHolder.java
To accepte listener and invoke callback.
public class RoutineViewHolder extends GroupViewHolder implements View.OnClickListener {
private TextView mTextView;
private Button btnAdd;
public RoutineViewHolder(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.exp_routine);
btnAdd = itemView.findViewById(R.id.btn_add);
itemView.setOnClickListener(this);
}
public void bind(final Routine routine, final ListActionListener listActionListener) {
mTextView.setText(routine.getTitle());
btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listActionListener.onAddTaskClicked(routine);
}
});
}
}
Bingo.... Run the code... :)
Have you tried to call setChildClickListener of your ExpandableAdapter object from your activity?
Have a look at this:
ExpandableAdapter adapter=new ExpandableAdapter(myExpandableGroupList);
adapter.setChildClickListener(new OnCheckChildClickListener() {
#Override
public void onCheckChildCLick(View v, boolean checked, CheckedExpandableGroup group,int childIndex) {
}
});
I hope this helps you.
Hey I'm doing filtering data on my project using bottom Sheet with view-pager and two fragments i can pass data from activity to view-pager adapter and get in fragment through constructor but how can i get data from fragment to activity using bottom-sheet
this is how i send data from activity
adapter = new PagerAdapters(this.getSupportFragmentManager(),
tabLayout.getTabCount(),_id);
and receive data with constructor in fragment
public Filterfragment(String _id) {
this._id = _id;
}
And I'm using recyclerview to show data like this
So how can i send id of the item to activity so i can reload my recyclerview data when the apply button click.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/bottom_sheet"
android:background="#android:color/white"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabPadding="0dp"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_below="#id/tabs"
android:layout_above="#id/applyBtn"
android:layout_height="match_parent"
/>
<Button
android:id="#+id/applyBtn"
android:layout_width="match_parent"
android:text="Apply"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content" />
</RelativeLayout>
This is main recyclerview adapter
public class FilterAdapter extends RecyclerView.Adapter<FilterAdapter.FilterViewHolder> {
private static final String TAG = "FilterAdapter";
Context context;
List<TagTypeResult> tagTypeModels;
public static int current_pos = -1;
TagAdapter tagAdapter;
int rotationAngle = 0;
public FilterAdapter(Context context, List<TagTypeResult> tagTypeModels) {
this.context = context;
this.tagTypeModels = tagTypeModels;
}
#NonNull
#Override
public FilterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.filter_row_item,parent,false);
return new FilterAdapter.FilterViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull FilterViewHolder filterViewHolder, int i) {
TagTypeResult tagTypeModel = tagTypeModels.get(i);
filterViewHolder.txt.setText(tagTypeModel.getName());
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
if (tagTypeModel.getTagsLists() != null) {
if (tagTypeModel.getTagsLists().size() <= 0) {
filterViewHolder.arrow.setVisibility(View.GONE);
filterViewHolder.arrow.setRotationX(180);
} else {
filterViewHolder.arrow.setVisibility(View.VISIBLE);
filterViewHolder.arrow.setRotationX(0);
}
}else {
filterViewHolder.arrow.setVisibility(View.GONE);
}
tagAdapter = new TagAdapter(context, tagTypeModel.getTagsLists(), new TagInterface() {
#Override
public void tagClick(View view, int pos, String tagID) {
Log.d(TAG, "tagClick: "+tagID);
}
});
filterViewHolder.sub_list_recycler.setAdapter(tagAdapter);
tagAdapter.notifyDataSetChanged();
if (current_pos == filterViewHolder.getAdapterPosition()){
if (filterViewHolder.sub_list_recycler.getVisibility() == View.GONE) {
filterViewHolder.sub_list_recycler.setVisibility(View.VISIBLE);
}else {
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
}
}else {
Log.i(TAG, "onBindViewHolder: sublist gone "+tagTypeModel.getName());
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
return tagTypeModels.size();
}
class FilterViewHolder extends RecyclerView.ViewHolder {
TextView txt;
ImageView arrow;
RecyclerView sub_list_recycler;
RelativeLayout linearLayout;
FilterViewHolder(#NonNull View itemView) {
super(itemView);
txt = itemView.findViewById(R.id.txt);
arrow = itemView.findViewById(R.id.arrow);
linearLayout = itemView.findViewById(R.id.main_cat_lay);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "onClick: "+current_pos);
if (current_pos != getAdapterPosition()) {
current_pos = getAdapterPosition();
notifyDataSetChanged();
}
else{
current_pos = -1;
notifyDataSetChanged();
}
}
});
sub_list_recycler = itemView.findViewById(R.id.sub_list_recycler);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context) {
#Override
public boolean canScrollVertically() {
return false;
}
};
sub_list_recycler.setLayoutManager(mLayoutManager);
sub_list_recycler.addItemDecoration(new SimpleDividerItemDecoration(context));
}
}
}
sub recyclerView adapter :
public class TagAdapter extends RecyclerView.Adapter<TagAdapter.TagViewHolder> {
private static final String TAG = "SublistAdapter";
Context context;
List<TagsList> tagsLists;
int pos = -1;
TagInterface tagInterface;
public TagAdapter(Context context, List<TagsList> tagsLists,TagInterface tagInterface) {
this.context = context;
this.tagsLists = tagsLists;
this.tagInterface = tagInterface;
}
#NonNull
#Override
public TagViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tag_item,parent,false);
return new TagAdapter.TagViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull TagViewHolder tagViewHolder, int i) {
TagsList tagsList = tagsLists.get(i);
tagViewHolder.tagtxt.setText(tagsList.getName());
if (tagsList.isChecked()){
tagViewHolder.tagName.setChecked(true);
}else {
tagViewHolder.tagName.setChecked(false);
}
}
#Override
public int getItemCount() {
return tagsLists.size();
}
public class TagViewHolder extends RecyclerView.ViewHolder {
TextView tagtxt;
CheckBox tagName;
RelativeLayout childClik;
public TagViewHolder(#NonNull View itemView) {
super(itemView);
//pri_txt = itemView.findViewById(R.id.pri_txt);
tagName = itemView.findViewById(R.id.tagName);
tagtxt = itemView.findViewById(R.id.tagtxt);
childClik = itemView.findViewById(R.id.childClik);
tagName.setEnabled(false);
childClik.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isChecked = true;
if (isChecked)
{
tagsLists.get(getAdapterPosition()).setChecked(true);
tagName.setChecked(true);
tagInterface.tagClick(v,getAdapterPosition(),tagsLists.get(getAdapterPosition()).get_id());
Toast.makeText(context, "[pos]"+tagsLists.get(getAdapterPosition()).get_id(), Toast.LENGTH_SHORT).show();
}else
{
tagsLists.get(getAdapterPosition()).setChecked(false);
tagName.setChecked(false);
}
}
});
}
}
}
I have created a list view with multiple items in row. I have also created a search box above. I want to implement search functionality on the basis of particular fields of the list. How can I achieve this? Any help will be appreciated.
You have to use model, listview, and customadapter with filtering for this.
I have created a demo for this.
Suppose you have a model named Product, and you are displaying its content in a custom listview where name and price are displayed in a textview. I mean in a custom row having two textviews, and you want to filter the list by one of the field of custom row. Here I have filtered with "name"
Screenshots:
Initial
Filtered
Source code
Model
public class Product {
public String name;
public Integer price;
public Product(String name, Integer price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
Activity with custom adapter and listview
public class MainActivity extends Activity {
private LinearLayout llContainer;
private EditText etSearch;
private ListView lvProducts;
private ArrayList<Product> mProductArrayList = new ArrayList<Product>();
private MyAdapter adapter1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialize();
// Add Text Change Listener to EditText
etSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Call back the Adapter with current character to Filter
adapter1.getFilter().filter(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
private void initialize() {
etSearch = (EditText) findViewById(R.id.etSearch);
lvProducts = (ListView)findViewById(R.id.lvOS);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mProductArrayList.add(new Product("a", 100));
mProductArrayList.add(new Product("b", 200));
mProductArrayList.add(new Product("c", 300));
mProductArrayList.add(new Product("d", 400));
mProductArrayList.add(new Product("e", 500));
mProductArrayList.add(new Product("f", 600));
mProductArrayList.add(new Product("g", 700));
mProductArrayList.add(new Product("h", 800));
mProductArrayList.add(new Product("i", 900));
mProductArrayList.add(new Product("j", 1000));
mProductArrayList.add(new Product("k", 1100));
mProductArrayList.add(new Product("l", 1200));
mProductArrayList.add(new Product("m", 1000));
mProductArrayList.add(new Product("n", 1300));
mProductArrayList.add(new Product("o", 1400));
mProductArrayList.add(new Product("p", 1500));
adapter1 = new MyAdapter(MainActivity.this, mProductArrayList);
lvProducts.setAdapter(adapter1);
}
// Adapter Class
public class MyAdapter extends BaseAdapter implements Filterable {
private ArrayList<Product> mOriginalValues; // Original Values
private ArrayList<Product> mDisplayedValues; // Values to be displayed
LayoutInflater inflater;
public MyAdapter(Context context, ArrayList<Product> mProductArrayList) {
this.mOriginalValues = mProductArrayList;
this.mDisplayedValues = mProductArrayList;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return mDisplayedValues.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
LinearLayout llContainer;
TextView tvName,tvPrice;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.row, null);
holder.llContainer = (LinearLayout)convertView.findViewById(R.id.llContainer);
holder.tvName = (TextView) convertView.findViewById(R.id.tvName);
holder.tvPrice = (TextView) convertView.findViewById(R.id.tvPrice);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvName.setText(mDisplayedValues.get(position).name);
holder.tvPrice.setText(mDisplayedValues.get(position).price+"");
holder.llContainer.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, mDisplayedValues.get(position).name, Toast.LENGTH_SHORT).show();
}
});
return convertView;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,FilterResults results) {
mDisplayedValues = (ArrayList<Product>) results.values; // has the filtered values
notifyDataSetChanged(); // notifies the data with new filtered values
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults(); // Holds the results of a filtering operation in values
ArrayList<Product> FilteredArrList = new ArrayList<Product>();
if (mOriginalValues == null) {
mOriginalValues = new ArrayList<Product>(mDisplayedValues); // saves the original data in mOriginalValues
}
/********
*
* If constraint(CharSequence that is received) is null returns the mOriginalValues(Original) values
* else does the Filtering and returns FilteredArrList(Filtered)
*
********/
if (constraint == null || constraint.length() == 0) {
// set the Original result to return
results.count = mOriginalValues.size();
results.values = mOriginalValues;
} else {
constraint = constraint.toString().toLowerCase();
for (int i = 0; i < mOriginalValues.size(); i++) {
String data = mOriginalValues.get(i).name;
if (data.toLowerCase().startsWith(constraint.toString())) {
FilteredArrList.add(new Product(mOriginalValues.get(i).name,mOriginalValues.get(i).price));
}
}
// set the Filtered result to return
results.count = FilteredArrList.size();
results.values = FilteredArrList;
}
return results;
}
};
return filter;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/etSearch"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<ListView
android:id="#+id/lvProducts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
></ListView>
</LinearLayout>
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_weight="1"
/>
<TextView
android:id="#+id/tvPrice"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:singleLine="true"
android:layout_weight="1"
/>
</LinearLayout>
Implement filterable in your customadapter class.
public class MainActivity extends AppCompatActivity {
String names[] = {"Apple","Banana","Kiwi","Oranges","Watermelon"};
String emails[] = {"This is apple","This is banana","This is kiwi","This is oranges","This is watermelon"};
int images[] = {R.drawable.apple,R.drawable.banana,R.drawable.kiwi,R.drawable.oranges,R.drawable.watermelon};
List<ItemsModel> itemsModelList = new ArrayList<>();
ListView listView;
CustomAdapter customAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listview);
for(int i = 0;i < names.length;i++){
ItemsModel itemsModel = new ItemsModel(names[i],emails[i],images[i]);
itemsModelList.add(itemsModel);
}
customAdapter = new CustomAdapter(itemsModelList,this);
listView.setAdapter(customAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_menu,menu);
MenuItem menuItem = menu.findItem(R.id.searchView);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
Log.e("Main"," data search"+newText);
customAdapter.getFilter().filter(newText);
return true;
}
});
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if(id == R.id.searchView){
return true;
}
return super.onOptionsItemSelected(item);
}
public class CustomAdapter extends BaseAdapter implements Filterable {
private List<ItemsModel> itemsModelsl;
private List<ItemsModel> itemsModelListFiltered;
private Context context;
public CustomAdapter(List<ItemsModel> itemsModelsl, Context context) {
this.itemsModelsl = itemsModelsl;
this.itemsModelListFiltered = itemsModelsl;
this.context = context;
}
#Override
public int getCount() {
return itemsModelListFiltered.size();
}
#Override
public Object getItem(int position) {
return itemsModelListFiltered.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = getLayoutInflater().inflate(R.layout.row_items,null);
TextView names = view.findViewById(R.id.name);
TextView emails = view.findViewById(R.id.email);
ImageView imageView = view.findViewById(R.id.images);
names.setText(itemsModelListFiltered.get(position).getName());
emails.setText(itemsModelListFiltered.get(position).getEmail());
imageView.setImageResource(itemsModelListFiltered.get(position).getImages());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.e("main activity","item clicked");
startActivity(new Intent(MainActivity.this,ItemsPreviewActivity.class).putExtra("items",itemsModelListFiltered.get(position)));
}
});
return view;
}
#Override
public Filter getFilter() {
Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(constraint == null || constraint.length() == 0){
filterResults.count = itemsModelsl.size();
filterResults.values = itemsModelsl;
}else{
List<ItemsModel> resultsModel = new ArrayList<>();
String searchStr = constraint.toString().toLowerCase();
for(ItemsModel itemsModel:itemsModelsl){
if(itemsModel.getName().contains(searchStr) || itemsModel.getEmail().contains(searchStr)){
resultsModel.add(itemsModel);
}
filterResults.count = resultsModel.size();
filterResults.values = resultsModel;
}
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
itemsModelListFiltered = (List<ItemsModel>) results.values;
notifyDataSetChanged();
}
};
return filter;
}
}
}
full tutorial can be found here:
listview with search and onItemClickListner
for this, you first need to add an edittext, where you will type to filter data from the list,
then enable filteration in the list,
editText = (EditText) findViewById(R.id.searchList);
adapter = new CustomListViewAdapter(this,
R.layout.list_row, rowItems);
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
Then you need to add TextChangeListener() for the edittext,
editText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
public void afterTextChanged(Editable arg0) {
MyActivityName.this.adapter.getFilter().filter(arg0);
}
});
You can set a TextWatcher for your search box and change your Cursor on onTextChanged() on TextWatcher like Codes below :
TextWatcher filterNameTextWatcher = new TextWatcher()
public void beforeTextChanged(CharSequence s, int start, int count,int after)
{
}
public void onTextChanged(CharSequence s,int start, int before,int count)
{
Cursor FilteredNameList = ZoneCardDBAdapter.instance.CursorFilteredName(s.toString());
Listadapter.changeCursor(FilteredNameList);
}
#Override
public void afterTextChanged(Editable arg0)
{
}
};
EditText filterTextName = (EditText)this.findViewById(R.id.edtZoneCardNameFilter);
filterTextCPName.addTextChangedListener(filterNameTextWatcher);
Use below kind of method.
your edit text box.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable theWatchedText) {
}
});
}
SearchWithMenuActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SearchWithMenuActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="#layout/expand_layout"
android:id="#+id/recycler_view"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
search_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/app_bar_search"
android:icon="#drawable/ic_search_black_24dp"
android:title="#string/search"
app:showAsAction="ifRoom|withText"
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
</menu>
expand_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:background="?attr/selectableItemBackground"
android:elevation="6dp">
<androidx.cardview.widget.CardView
android:id="#+id/cardview"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
app:cardCornerRadius="5dp"
app:cardUseCompatPadding="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/layout_click"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/srNo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="#string/srNo"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/part_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="8dp"
android:text="#string/enter_the_name"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="#+id/arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:contentDescription="#string/todo"
android:padding="8dp"
android:src="#drawable/arrow_down_24" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
ExpandModel.kt
package com.materialsouk.allcodeapp.models
class ExpandModel(private var name:String,private var expanded:Boolean = false) {
fun setName(name: String) {
this.name = name
}
fun getName():String{
return name
}
fun setExpanded(expanded: Boolean) {
this.expanded = expanded
}
fun getExpanded():Boolean{
return expanded
}
}
ExpandAdapter.kt
package com.materialsouk.allcodeapp.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.materialsouk.allcodeapp.R
import java.util.ArrayList
import android.view.animation.Animation.RELATIVE_TO_SELF
import android.view.animation.RotateAnimation
import android.widget.ImageView
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.materialsouk.allcodeapp.models.ExpandModel
class ExpandAdapter(private var expandList: ArrayList<ExpandModel>) :
RecyclerView.Adapter<ExpandAdapter.ViewHolder>() {
class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
val srNo: TextView = itemView.findViewById(R.id.srNo)
val nameTxt: TextView = itemView.findViewById(R.id.part_name)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view: View =
LayoutInflater.from(parent.context).inflate(R.layout.expand_layout, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.srNo.text = (position + 1).toString()
holder.nameTxt.text = expandList[position].getName()
}
override fun getItemCount(): Int {
return expandList.size
}
}
SearchWithMenuActivity.kt
package com.materialsouk.allcodeapp
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.RecyclerView
import com.materialsouk.allcodeapp.adapters.ExpandAdapter
import com.materialsouk.allcodeapp.models.ExpandModel
import java.util.*
import kotlin.collections.ArrayList
class SearchWithMenuActivity : AppCompatActivity() {
private lateinit var arrayList: ArrayList<ExpandModel>
private lateinit var adapter: ExpandAdapter
private lateinit var recyclerView: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search_with_menu)
recyclerView = findViewById(R.id.recycler_view)
arrayList = ArrayList()
arrayList.add(ExpandModel("Meet", false))
arrayList.add(ExpandModel("Ankit", false))
arrayList.add(ExpandModel("Rushil", false))
arrayList.add(ExpandModel("Abhishek", false))
arrayList.add(ExpandModel("Modi", false))
arrayList.add(ExpandModel("Ghree", false))
arrayList.add(ExpandModel("Kirtan", false))
arrayList.add(ExpandModel("Ankita", false))
arrayList.add(ExpandModel("Soham", false))
arrayList.add(ExpandModel("Ganesh", false))
arrayList.add(ExpandModel("Dixit", false))
arrayList.add(ExpandModel("Ankash", false))
arrayList.add(ExpandModel("Parth", false))
arrayList.add(ExpandModel("Pranav", false))
arrayList.add(ExpandModel("Ankit Sir", false))
arrayList.add(ExpandModel("Priya Mem", false))
arrayList.add(ExpandModel("Jinal Mem", false))
arrayList.add(ExpandModel("Bhumi", false))
arrayList.add(ExpandModel("Nidhi", false))
arrayList.add(ExpandModel("Hardik", false))
arrayList.add(ExpandModel("Mayank", false))
arrayList.add(ExpandModel("Kaushik", false))
arrayList.add(ExpandModel("Rinku", false))
arrayList.add(ExpandModel("Mom", false))
adapter = ExpandAdapter(arrayList)
recyclerView.adapter = adapter
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.search_menu, menu)
val search = menu.findItem(R.id.app_bar_search)
val searchView = search.actionView as SearchView
searchView.maxWidth = android.R.attr.width
searchView.queryHint = "Search"
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
#SuppressLint("NotifyDataSetChanged")
override fun onQueryTextChange(newText: String?): Boolean {
val freeServiceModelArrayList: ArrayList<ExpandModel> = ArrayList()
for (i in arrayList) {
if (i.getName().lowercase(Locale.getDefault()).contains(
newText!!.lowercase(
Locale.getDefault()
)
)
) {
freeServiceModelArrayList.add(i)
}
}
adapter = ExpandAdapter(freeServiceModelArrayList)
recyclerView.adapter = adapter
adapter.notifyDataSetChanged()
return true
}
})
return super.onCreateOptionsMenu(menu)
}
}
I have multiple options for a poll and user can select only one option. i am getting options in recycler view with a checkbox and textview.
i want to uncheck previous selected checkbox if user select another checkbox and get selected text by pressing submit button.
here is my recycler view code.
public class Poll_Options_recyclerView_Adapter extends RecyclerView.Adapter<Poll_Options_recyclerView_Adapter.MyViewHolder> {
public List<Poll_Option_Result> result = new ArrayList<>();
Context mycontext;
public Poll_Options_recyclerView_Adapter(List<Poll_Option_Result> result, Context context) {
this.result = result;
this.mycontext = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_option_rec_list, parent, false);
return new MyViewHolder(itemView, mycontext, result);
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView poll_option;
CheckBox checkBox;
List<Poll_Option_Result> result_List = new ArrayList<>();
Context mycontext;
public MyViewHolder(View itemView, Context mycontext, List<Poll_Option_Result> result_List) {
super(itemView);
this.result_List = result_List;
this.mycontext = mycontext;
poll_option = (TextView) itemView.findViewById(R.id.optionA);
checkBox=(CheckBox)itemView.findViewById(R.id.check_box);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
}
}
#Override
public void onBindViewHolder(Poll_Options_recyclerView_Adapter.MyViewHolder holder, int position) {
final Poll_Option_Result ResultList = result.get(position);
holder.poll_option.setText(ResultList.getOption());
}
#Override
public int getItemCount() {
return result.size();
}
}
and here is my recycler view custom xml code.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="5"
>
<CheckBox
android:id="#+id/check_box"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"/>
<TextView
android:layout_width="0dp"
android:layout_weight="4.5"
android:layout_height="wrap_content"
android:text="xyz"
android:layout_marginLeft="20dp"
android:textColor="#color/colortoolbartitle"
android:padding="5dp"
android:id="#+id/optionA"/>
private int mCheckedPostion = -1;// no selection by default
Done by adding this code in onBindViewHolder
#Override
public void onBindViewHolder(final Poll_Options_recyclerView_Adapter.MyViewHolder holder, final int position) {
final Poll_Option_Result ResultList = result.get(position);
holder.poll_option.setText(ResultList.getOption());
//check checkbox and uncheck previous selected button
holder.checkBox.setChecked(position == mCheckedPostion);
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position == mCheckedPostion) {
holder.checkBox.setChecked(false);
StringGen.username = "";
mCheckedPostion = -1;
} else {
mCheckedPostion = position;
StringGen.username = holder.poll_option.getText().toString();
Toast.makeText(mycontext, "select : "+position+holder.poll_option.getText(), Toast.LENGTH_SHORT).show();
notifyDataSetChanged();
}
}
});
}
I have a recyclerview which shows multiple cardviews with items. In the recyclerview, I have a popup menu to delete that current cardview.
When the dataset is empty I would like to show an empty view. Something with an image and text saying "empty" I have tried some online examples. No success.
My layout is a cardview(card_view_row.xml) is a simple view with a cardview that shows a few items.
Here is my recyclerview
public class AlarmRecyclerViewAdapter extends
RecyclerView.Adapter<AlarmRecyclerViewAdapter.DataObjectHolder> {
private ArrayList<Alarm> mDataset;
private static AlarmRecyclerViewAdapter.MyClickListener myClickListener;
private AlarmDataAccess dataAccess;
private Alarm alarm;
private int switchOn = 1;
private int switchOff = 0;
private static Context context;
private PopupMenu popupMenu;
public static class DataObjectHolder extends RecyclerView.ViewHolder
implements View
.OnClickListener {
TextView label;
TextView dateTime;
TextView label2;
TextView textViewLabel;
TextView gender;
TextView daysofweek;
Switch aSwitch;
ImageView trash;
public DataObjectHolder(View itemView) {
super(itemView);
dateTime = (TextView) itemView.findViewById(R.id.textView2);
label = (TextView) itemView.findViewById(R.id.textView);
label2 =(TextView) itemView.findViewById(R.id.textView3);
aSwitch = (Switch)itemView.findViewById(R.id.switchButton);
trash = (ImageView)itemView.findViewById(R.id.imageTrash);
gender = (TextView)itemView.findViewById(R.id.textViewGender);
daysofweek = (TextView)itemView.findViewById(R.id.textViewDays);
textViewLabel = (TextView)itemView.findViewById(R.id.textViewLabel);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
public void setOnItemClickListener(AlarmRecyclerViewAdapter.MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
public AlarmRecyclerViewAdapter(ArrayList<Alarm> myDataset, Context context2) {
mDataset = myDataset;
context = context2;
}
#Override
public AlarmRecyclerViewAdapter.DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_row, parent, false);
AlarmRecyclerViewAdapter.DataObjectHolder dataObjectHolder = new AlarmRecyclerViewAdapter.DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(final AlarmRecyclerViewAdapter.DataObjectHolder holder, final int position) {
boolean status = false;
int gender;
alarm = new Alarm();
dataAccess = new AlarmDataAccess(context);
dataAccess.open();
holder.label.setText(mDataset.get(position).getHourOfDay() + ":" + mDataset.get(position).getMinute() + " " + mDataset.get(position).getTimeSet());
holder.textViewLabel.setText(mDataset.get(position).getLabel());
gender = mDataset.get(position).getGender();
if(gender == 0){
holder.gender.setText("Male voice");
}else{
holder.gender.setText("Female voice");
}
holder.daysofweek.setText(mDataset.get(position).getDays());
holder.label2.setText("" + mDataset.get(position).getAffirmationName());
holder.trash.setImageResource(R.drawable.menu2);
if( mDataset.get(position).getStatus() == 0){
status = false;
}else {
status = true;
}
holder.aSwitch.setChecked(status);
holder.aSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isPressed()) {
if (isChecked) {
mDataset.get(position).setStatus(switchOn);
} else {
mDataset.get(position).setStatus(switchOff);
}
alarm.setId(mDataset.get(position).getId());
alarm.setStatus(mDataset.get(position).getStatus());
dataAccess.updateStatus(alarm);
}
}
});
holder.trash.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
popupMenu = new PopupMenu(AlarmRecyclerViewAdapter.context, v);
popupMenu.inflate(R.menu.popup_menu);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.edit:
long selectedAlarmId = mDataset.get(position).getId();
Intent intent = new Intent(AlarmRecyclerViewAdapter.context, EditAlarmActivity.class);
intent.putExtra("id", selectedAlarmId);
intent.putExtra("Edit", "FromEdit");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmRecyclerViewAdapter.context.startActivity(intent);
return true;
case R.id.delete:
long id = mDataset.get(position).getId();
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, mDataset.size());
dataAccess.deleteAlarm(id);
return true;
}
return false;
}
});
popupMenu.show();
}
});
}
public void deleteItem(int index) {
mDataset.remove(index);
notifyItemRemoved(index);
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
My recyclerview is inside a fragment view
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_place">
<ImageButton
android:id="#+id/add_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="end|bottom"
android:tint="#color/icon"
android:elevation="12dp"
android:background="#drawable/oval_ripple"
tools:backgroundTint="#96ceb4"
android:src="#android:drawable/ic_input_add"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="12dp"
android:layout_marginTop="14dp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:layout_below="#+id/add_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp" />
</RelativeLayout>
Is there a way to detect if the data set is empty to show an empty view with text saying empty or something? I need this done inside recyclerview since I am deleting items inside there.
EDIT
I finally figured out how to do it. I am posting this incase anyone else has the same problem.
http://akbaribrahim.com/empty-view-for-androids-recyclerview/
For my personal use I use this trick :
I use two LinearLayout, one with my RecyclerView and another with a simple TextView saying "Empty". Both are in the same parent view.
<LinearLayout
android:id="#+id/linearContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible">
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scrollbars="vertical" />
</LinearLayout>
<LinearLayout
android:id="#+id/linearEmpty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textEmpty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:text="#string/dialog_no_result"
android:textColor="#color/cardview_dark_background" />
</LinearLayout>
And when I update my list of item I call this method :
if (linearContent != null && linearEmpty != null) {
if (mListItems.isEmpty()) {
linearContent.setVisibility(View.GONE);
linearEmpty.setVisibility(View.VISIBLE);
textEmpty.setVisibility(View.VISIBLE);
} else {
linearContent.setVisibility(View.VISIBLE);
linearEmpty.setVisibility(View.GONE);
textEmpty.setVisibility(View.GONE);
}
}
Then I use the same layout, but just change the visibility of some objects.
Hope it help.