I want filter the recycleView by searchView.
I add xml file to menu.
When the app run she stop when the fragment open.
When I put break point I found the problem in line: SearchView searchView = (SearchView) searchItem.getActionView() - in method onCreateOptionsMenu.
why this happening? (the addapter create in fragment)
In xml menu I changed to
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="android.support.v7.widget.SearchView"/>
#SuppressLint("ValidFragment")
public class AvailableDrivesFragment extends Fragment {
public RecyclerView drivesRecyclerView;
public LinearLayout details;
public List<Drive> drives = new ArrayList<>();
public TextView textDetails;
public Button buttonChoose;
IDataBase fb = FactoryDataBase.getDataBase();
private DrivesRecycleViewAdapter adapter;
private Menu menu;
Driver driver;
#SuppressLint("ValidFragment")
AvailableDrivesFragment(Driver e) {
this.driver = e;
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_available_drives, container, false);
textDetails = v.findViewById(R.id.text_details);
details = v.findViewById(R.id.linear_details);
details.setVisibility(View.GONE);
getActivity().setTitle("Available Drives");
drivesRecyclerView = v.findViewById(R.id.my_list);
drivesRecyclerView.setHasFixedSize(true);
drivesRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new DrivesRecycleViewAdapter();
drives = fb.getAvailableDrives();
drivesRecyclerView.setAdapter(adapter);
setHasOptionsMenu(true);
return v;
}
#Override
public void onDestroy() {
Firebase_DBManager.stopNotifyToDriveList();
super.onDestroy();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();//here stop working
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
try {
adapter.getFilter().filter(newText);
}
catch (Exception r) {
r.printStackTrace();
}
return false;
}
});
}
public class DrivesRecycleViewAdapter extends RecyclerView.Adapter<DrivesRecycleViewAdapter.DriveViewHolder> implements Filterable
{
public List<Drive> drivefull;
public DrivesRecycleViewAdapter() {
this.drivefull = new ArrayList<>(drives);
;
}
#Override
public DriveViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(getActivity()).inflate(R.layout.item_drive, parent, false);
return new DriveViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull DriveViewHolder holder, int position) {
Drive drive = drives.get(position);
holder.nameTextView.setText(drive.getName());
holder.nameTextView.setTextSize(20);
holder.phoneTextView.setText(drive.getStartAddress());
holder.phoneTextView.setTextSize(16);
}
#Override
public int getItemCount() {
return drives.size();
}
#Override
public Filter getFilter() {
return filter;
}
public Filter filter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Drive> filteredList = new ArrayList<>();//new list that contained only filtered items
if (constraint == null || constraint.length() == 0)//we what to show all the results becuse we don't what filtering
{
filteredList.addAll(drivefull);
} else { //we what to filter the list
String filterPattern = constraint.toString().toLowerCase().trim(); // sting that takes the input
for (Drive item : drivefull) {
if (item.getName().toLowerCase().contains((filterPattern))) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
drives.clear();
drives.addAll((List) results.values);
notifyDataSetChanged();
}
};
class DriveViewHolder extends RecyclerView.ViewHolder {
TextView phoneTextView;
TextView nameTextView;
public DriveViewHolder(final View itemView) {
super(itemView);
phoneTextView = itemView.findViewById(R.id.phone_item_drive);
nameTextView = itemView.findViewById(R.id.name_item_drive);
itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Select Action");
MenuItem detailm = menu.add(Menu.NONE, 1, 1, "view details");
detailm.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Drive drive = drives.get(getAdapterPosition());
textDetails.setText(drive.toString());
details.setVisibility(View.VISIBLE);
return true;
}
});
MenuItem addDrive = menu.add(Menu.NONE, 1, 1, "take drive");
addDrive.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
final Drive drive = drives.get(getAdapterPosition());
fb.changeStatus(drive.getId(), driver, DriveStatus.TREATMENT, new IDataBase.Action() {
#Override
public void onSuccess() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("The drive is in your care!")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String mail = drive.getEmail();
String[] mails = mail.split(",");
Intent in = new Intent(Intent.ACTION_SEND);
in.putExtra(Intent.EXTRA_EMAIL, mails);
in.putExtra(Intent.EXTRA_SUBJECT, "get taxi");
in.putExtra(Intent.EXTRA_TEXT, "taxi will coming to you in few minutes");
in.setType("message/rfc822");
startActivity(Intent.createChooser(in, "choose email"));
}
});
AlertDialog alert = builder.create();
alert.show();
drives.remove(getAdapterPosition());
drivesRecyclerView.getAdapter().notifyDataSetChanged();
}
#Override
public void onFailure(Exception exception) {
Toast.makeText(getActivity(), "הלקיחה נכשלה", Toast.LENGTH_LONG).show();
}
#Override
public void onProgress(String status, double percent) {
;
}
});
return true;
}
});
}
});
}
}
}
}
Related
**I want to know how to click the items in childRecyclerview show different fragment, I think we should try to modify childAdapter, I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.
hear is my code
**
//workflow fragment
public class WorkflowFragment extends Fragment {
private Context mContext;
private String[] workflowHeading;
private String[] workflowContent;
private int[] imageResourceId;
private RecyclerView recyclerview;
private List<Workflow> workflowList;
private WorkflowAdapter workflowAdapter;
private View view;
public static WorkflowFragment newInstance(String param1, String param2) {
WorkflowFragment fragment = new WorkflowFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
mContext = getActivity();
setHasOptionsMenu(true);
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(view==null) {
view = inflater.inflate(R.layout.fragment_workflow, container, false);
}
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
dataInitialize();
recyclerview = view.findViewById(R.id.workflow_recyclerview);
recyclerview.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerview.setHasFixedSize(true);
workflowAdapter =new WorkflowAdapter(getContext(),workflowList);
recyclerview.setAdapter(workflowAdapter);
workflowAdapter.notifyDataSetChanged();
}
private void dataInitialize() {
//list1
List<String> nestedList1 = new ArrayList<>();
nestedList1.add("A");
nestedList1.add("B");
nestedList1.add("C");
nestedList1.add("D");
nestedList1.add("E");
nestedList1.add("F");
nestedList1.add("G");
//list2
List<String>nestedList2 = new ArrayList<>();
nestedList2.add("H");
nestedList2.add("I");
nestedList2.add("G");
nestedList2.add("K");
//list3
List<String>nestedList3 = new ArrayList<>();
nestedList3.add("L");
nestedList3.add("M");
nestedList3.add("N");
nestedList3.add("P");
nestedList3.add("P");
nestedList3.add("Q");
nestedList3.add("R");
nestedList3.add("S");
//list4
List<String>nestedList4 = new ArrayList<>();
nestedList4.add("T");
nestedList4.add("U");
nestedList4.add("V");
nestedList4.add("W");
//list5
List<String>nestedList5 = new ArrayList<>();
nestedList5.add("X");
//list6
List<String>nestedList6 = new ArrayList<>();
nestedList6.add("Y");
nestedList6.add("Z");
workflowList = new ArrayList<>();
workflowList.add(new Workflow("1",nestedList1));
workflowList.add(new Workflow("2",nestedList2));
workflowList.add(new Workflow("3",nestedList3));
workflowList.add(new Workflow("4",nestedList4));
workflowList.add(new Workflow("5",nestedList5));
workflowList.add(new Workflow("6",nestedList6));
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.menu_item,menu);
MenuItem searchItem = menu.findItem(R.id.search_action);
if(searchItem!=null){
SearchView searchView = (SearchView) searchItem.getActionView(); //here stop working
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setQueryHint("Search Here!");
searchView.setIconified(false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
workflowAdapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
notifyItemChanged()
workflowAdapter.getFilter().filter(newText);
return false;
}
});
}
super.onCreateOptionsMenu(menu, inflater);
}
}
//ParentAdapter
public class WorkflowAdapter extends RecyclerView.Adapter<WorkflowAdapter.WorkflowViewHolder> implements Filterable{
Context context;
List<Workflow> worflowArrayList;
List<Workflow> worflowArrayListFull;
private List<String>nestedlist = new ArrayList<>();
public WorkflowAdapter(Context context, List<Workflow> worflowArrayList) {
this.context = context;
this.worflowArrayListFull = worflowArrayList;
this.worflowArrayList = new ArrayList<>(worflowArrayListFull);
}
#NonNull
#Override
public WorkflowViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.general_list_item,parent,false);
return new WorkflowViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull WorkflowViewHolder holder, int parentPosition) {
//-get element from your dataset at this position
//-replace the contents of the view with that element
Workflow workflow = worflowArrayList.get(parentPosition);
holder.tvHeading.setText(workflow.getItemText());
//holder.titleImage.setImageResource(model.titleImage);
boolean isExpandable = workflow.isExpandable();
holder.expandableLayout.setVisibility(isExpandable ? View.VISIBLE:View.GONE);
if(isExpandable){
holder.mArrowImage.setImageResource(R.drawable.ic_baseline_arrow_upward_24);
}else{
holder.mArrowImage.setImageResource(R.drawable.ic_baseline_arrow_downward_24);
}
NestedAdapter childAdapter = new NestedAdapter(nestedlist);
holder.nestedRecyclerView.setLayoutManager(new LinearLayoutManager(holder.itemView.getContext()));
holder.nestedRecyclerView.setHasFixedSize(true);
holder.nestedRecyclerView.setAdapter(childAdapter);
holder.linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch(holder.getAdapterPosition()){
case 1:
Toast.makeText(holder.itemView.getContext(), "Item 11 clicked. ", Toast.LENGTH_SHORT).show();
break;
}
workflow.setExpandable(!workflow.isExpandable());
nestedlist = workflow.getNestedList();
notifyItemChanged(holder.getAdapterPosition());
}
});
}
#Override
public int getItemCount() {
return worflowArrayList.size();
}
#Override
public Filter getFilter() {
return workflowFilter;
}
private final Filter workflowFilter = new Filter(){
#Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<Workflow> filteredWorkflowList = new ArrayList<>();
if (constraint == null || constraint.length() == 0){
filteredWorkflowList.addAll(worflowArrayListFull);
}else{
String filterPattern = constraint.toString().toLowerCase().trim();
for (Workflow workflow: worflowArrayListFull){
if(workflow.itemText.toLowerCase().contains(filterPattern))
filteredWorkflowList.add(workflow);
}
}
FilterResults results = new FilterResults();
results.values = filteredWorkflowList;
results.count = filteredWorkflowList.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
worflowArrayList.clear();
worflowArrayList.addAll((ArrayList)results.values);
notifyDataSetChanged();
}
};
public static class WorkflowViewHolder extends RecyclerView.ViewHolder{
private TextView tvHeading;
private LinearLayout linearLayout;
private RelativeLayout expandableLayout;
private ImageView mArrowImage;
private RecyclerView nestedRecyclerView;
public WorkflowViewHolder(#NonNull View itemView) {
super(itemView);
linearLayout=itemView.findViewById(R.id.linear_layout);
expandableLayout=itemView.findViewById(R.id.expandable_layout);
tvHeading = itemView.findViewById(R.id.tvHeading);
mArrowImage=itemView.findViewById(R.id.arro_imageview);
nestedRecyclerView = itemView.findViewById(R.id.child_rv);
}
}
}
//childAdapter
public class NestedAdapter extends RecyclerView.Adapter<com.larntech.myassistant_java.workflow.NestedAdapter.NestedViewHolder> {
private List<String> childItemList; /
public NestedAdapter(List<String> childItemList){
this.childItemList = childItemList;
}
#NonNull
#Override
public com.larntech.myassistant_java.workflow.NestedAdapter.NestedViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.nested_item,parent,false);
return new com.larntech.myassistant_java.workflow.NestedAdapter.NestedViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull com.larntech.myassistant_java.workflow.NestedAdapter.NestedViewHolder holder, int childPosition) {
holder.mTv.setText(childItemList.get(childPosition));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch(holder.getAdapterPosition()){
case 0:
DemoFragment demoFragment =new DemoFragment();
AppCompatActivity activity=(AppCompatActivity) view.getContext();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_workflow,demoFragment).addToBackStack(null).commit();
break;
case 1:
FragmentTwo fragmentTwo =new FragmentTwo();
AppCompatActivity activity2=(AppCompatActivity) view.getContext();
activity2.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_workflow,fragmentTwo).addToBackStack(null).commit();
break;
case 2:
Toast.makeText(holder.itemView.getContext(), "Item clicked. ", Toast.LENGTH_SHORT).show();
break;
}
}
});
}
#Override
public int getItemCount() {
return childItemList.size();
}
public class NestedViewHolder extends RecyclerView.ViewHolder{
private TextView mTv;
public NestedViewHolder(#NonNull View itemView) {
super(itemView);
mTv=itemView.findViewById(R.id.nestedItemTv);
}
}
}
I am using contextual action bar in my fragment("UnitsFragment.java") to delete and edit items of recyclerview. But when I come back from recyclerview adapter class("UnitsRv.java"). The context seems to be null. I tried returning context from adapter and it worked for function "prepareSelection". However for "onActionItemClicked" under ActionMode.callback, I need to get context so that I can use alertdialog for editing the items.
The "requireContext()" throws this error: Fragment UnitsFragment{e3a36c8 (b4957397-055a-4b1c-8af2-fee89a3e9b35)} not attached to a context.
Here are my codes.
UnitsFragment.java
public class UnitsFragment extends Fragment {
private static final String TAG = "UnitsFragment";
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<UnitsList> unitsLists = new ArrayList<>();
Activity mcontext = getActivity();
Context dcontext;
ActionMode actionMode;
public static ArrayList<UnitsList> selectionList = new ArrayList<>();
public static boolean isInActionMode = false;
List<String> list = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao().findUnitNameList();
public UnitsFragment() {
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_item_action, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_edit:
if (selectionList.size() == 1) {
final EditText editText = new EditText(requireContext());
new AlertDialog.Builder(requireContext())
.setTitle("Rename unit name").setView(editText)
.setPositiveButton("Rename", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
UnitsList unitsList = selectionList.get(0);
unitsList.setUnit_name(editText.getText().toString().trim());
isInActionMode = false;
((UnitsRv) mAdapter).changeDataItem(getCheckedLastPosition(), unitsList);
actionMode.finish();
selectionList.clear();
}
})
.create()
.show();
Toast.makeText(getContext(), "Edit", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
case R.id.menu_item_delete:
isInActionMode = false;
((UnitsRv) mAdapter).removeData(selectionList);
Toast.makeText(getContext(), "Delete", Toast.LENGTH_SHORT).show();
actionMode.finish();
selectionList.clear();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
}
};
private int getCheckedLastPosition() {
ArrayList<UnitsList> dataSet = UnitsRv.getDataSet();
for (int i = 0; i < dataSet.size(); i++) {
if (dataSet.get(i).equals(selectionList.get(0))) {
return i;
}
}
return 0;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
dcontext = rootView.getContext();
Log.d(TAG, "onCreateView1: " + dcontext);
recyclerView = rootView.findViewById(R.id.rv_units);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.HORIZONTAL));
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL));
layoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(layoutManager);
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
Log.d(TAG, "onCreateView: " + getContext());
mAdapter = new UnitsRv(mcontext,unitsLists);
recyclerView.setAdapter(mAdapter);
return rootView;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.add, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new:
final View customLayout = getLayoutInflater().inflate(R.layout.add_unit_dialog, null);
final EditText edt_unit_name = customLayout.findViewById(R.id.edt_new_unit_name);
final AlertDialog dialog = new AlertDialog.Builder(getContext())
.setView(customLayout)
.setTitle("Unit name")
.setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
Button ok_btn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button cancel_btn = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
ok_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String unit_name = edt_unit_name.getText().toString().trim();
if (!TextUtils.isEmpty(unit_name)) {
String old_unit_name = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.findByUnitName(unit_name);
if (old_unit_name == null) {
DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.insertUnits(new UnitsList(unit_name));
unitsLists.add(new UnitsList(unit_name));
dialog.dismiss();
} else {
edt_unit_name.setError("Unit already exists");
}
} else {
edt_unit_name.setError("Can't be empty");
}
}
});
cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
}
});
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists);
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
private void updateViewCounter() {
int counter = selectionList.size();
if (counter == 1) {
actionMode.setTitle(counter + "item selected");
} else {
actionMode.setTitle(counter + "items selected");
}
}
}
This is my Adapter class.
UnitsRv.java
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment();
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists) {
mcontext = context;
munitsLists = unitsLists;
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
unitsFragment.prepareSelection(mcontext,getAdapterPosition());
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
unitsFragment.prepareSelection(view.getContext(),getAdapterPosition());
return true;
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.units_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.unit_name.setText(munitsLists.get(position).getUnit_name());
if (UnitsFragment.isInActionMode){
if (UnitsFragment.selectionList.contains(munitsLists.get(position))){
holder.itemView.setBackgroundResource(R.color.colorSelected);
}
}
}
#Override
public int getItemCount() {
return munitsLists.size();
}
public static ArrayList<UnitsList> getDataSet() {
return munitsLists;
}
public void changeDataItem(int position, UnitsList unitsList) {
munitsLists.set(position, unitsList);
notifyDataSetChanged();
}
public void removeData(ArrayList<UnitsList> list) {
for (UnitsList unitsList : list) {
munitsLists.remove(unitsList);
}
notifyDataSetChanged();
}
}
First, you should not create instance of your UnitsFragment inside your adapter.
You can use EventBus to communicate between Activities, Fragments, Adapters, etc.
Or You can do your task using interface. like below.
Create an interface like this
public interface AdapterCallback {
void prepareSelection(Context context,int position);
}
In your UnitsFragment implement the above interface. like the following
public class UnitsFragment extends Fragment implements AdapterCallback{
// your other codes
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
// .... your other codes
Log.d(TAG, "onCreateView: " + getContext());
// modify below line like this
mAdapter = new UnitsRv(mcontext, unitsLists, this); // here you have to pass an extra parameter that will implement your callback method from adapter.
recyclerView.setAdapter(mAdapter);
return rootView;
}
// ... you other codes
#Override
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists,this); // add this as parameter.
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
// other codes
}
Now, inside your Adapter you need to add an extra argument in constructor of UnitsRv and call your interface method from adapter ussing mAdapterCallback.
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment(); // remove this line
private AdapterCallback mAdapterCallback; // add this line
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists, AdapterCallback callback) {
mcontext = context;
munitsLists = unitsLists;
this.mAdapterCallback = callback; // add this line
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
mAdapterCallback.prepareSelection(mcontext,getAdapterPosition()); // modify this line
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
mAdapterCallback.prepareSelection(view.getContext(),getAdapterPosition()); // modify this line
return true;
}
}
// your other codes....
}
You should check for your fragment is attached or not with isAdded()
place if(!isAdded()) return in your onActionItemClicked. and replace requireContext() with getContext() because requireContext() always throws IllegalStateException if fragment is not attached.
override onAttach method to save context in your fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context= context;
}
Hope this helps.
My MainActivity has a RecyclerView adapter, and data to this RecyclerView is added through a AlertDialog which passes the entered text to the MainActivity. The recycler view gets refreshed somehow when the positive button in the dialog is pressed even though I never call notifyItemInserted() or notifyDatasetChange() after passing the new input. I want to know how this happens, my guess is the recyclerview is somehow refreshed after the positive button is pressed in the dialog box
Custom AlertDialog Code:
public class CustomDialog extends AppCompatDialogFragment {
OnNoteAddedListener onNoteAddedListener;
public interface OnNoteAddedListener {
public void onClick(String note);
}
public CustomDialog(OnNoteAddedListener onNoteAddedListener) {
this.onNoteAddedListener = onNoteAddedListener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
final LayoutInflater inflater = getActivity().getLayoutInflater();
final View dialogLayout = inflater.inflate(R.layout.dialog_box, null);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(dialogLayout).setPositiveButton("Ok", new DialogInterface.OnClickListener() {#Override
public void onClick(DialogInterface dialog, int id) {
EditText addNote = dialogLayout.findViewById(R.id.note_text);
String note = addNote.getText().toString();
onNoteAddedListener.onClick(note);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
CustomDialog.this.getDialog().cancel();
}
});
return builder.create();
}
}
Adapter code:
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>
{
private static final String TAG = "RecyclerViewAdapter";
private List<String> notesList;
private Context mContext;
private SendPositionConnector sendPositionConnector;
public interface SendPositionConnector
{
public void sendPosition(int position);
}
public RecyclerViewAdapter(List<String> notesList, Context mContext)
{
this.notesList = notesList;
this.mContext = mContext;
this.sendPositionConnector = (MainActivity)mContext;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, final int position)
{
Log.d(TAG, "onBindViewHandler: called");
viewHolder.noteContent.setText(notesList.get(position));
viewHolder.parentLayout.setOnLongClickListener(new View.OnLongClickListener(){
#Override
public boolean onLongClick(View view)
{
Log.d(TAG, "onLongClick: long clicked on");
sendPositionConnector.sendPosition(position);
return false;
}
});
}
#Override
public int getItemCount()
{
return notesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView noteContent;
RelativeLayout parentLayout;
ImageView bullet;
public ViewHolder(#NonNull View itemView)
{
super(itemView);
bullet = itemView.findViewById(R.id.bullet);
noteContent = itemView.findViewById(R.id.text_content);
parentLayout = itemView.findViewById(R.id.parent_layout);
}
}
}
Activity Code:
public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.SendPositionConnector
{
private static final String TAG = "MainActivity";
private List<String> notesList = new ArrayList<>();
private RecyclerView recyclerView;
private RecyclerViewAdapter adapter;
private int position;
public AgentAsyncTask agentAsyncTask;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.my_recycler_view);
registerForContextMenu(recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
agentAsyncTask = new AgentAsyncTask(notesList, getApplicationContext(), true, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
adapter = new RecyclerViewAdapter(notesList, MainActivity.this);
recyclerView.setAdapter(adapter);
}
});
agentAsyncTask.execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.add_note:
showDialogBox(item);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onStop()
{
super.onStop();
new AgentAsyncTask(notesList, getApplicationContext(), false, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
}
}).execute();
}
#Override
protected void onDestroy()
{
super.onDestroy();
}
private boolean showDialogBox(MenuItem menuItem)
{
AppCompatDialogFragment dialogFragment = new CustomDialog(new CustomDialog.OnNoteAddedListener(){
#Override
public void onClick(String note)
{
Log.d(TAG, "onClick: "+ note);
notesList.add(note);
}
});
dialogFragment.show(getSupportFragmentManager(),"Adding");
return true;
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
#Override
public boolean onContextItemSelected(MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.delete:
notesList.remove(position);
adapter.notifyItemRemoved(position);
adapter.notifyItemRangeChanged(position, notesList.size());
return true;
default:
return false;
}
}
#Override
public void sendPosition(int position)
{
this.position = position;
}
private static class AgentAsyncTask extends AsyncTask<Void, Void, List<String>>
{
private List<String> notesList;
private boolean flag;
OnRead onRead;
Context context;
AppDataBase dataBase;
private static final String TAG = "AgentAsyncTask";
public interface OnRead
{
public void onRead(List<String> notesList);
}
private AgentAsyncTask(List<String> notesList,Context context,boolean flag, OnRead onRead)
{
this.notesList = notesList;
this.onRead = onRead;
this.flag = flag;
this.context = context;
}
#Override
protected List<String> doInBackground(Void... params)
{
dataBase = Room.databaseBuilder(context, AppDataBase.class, "database-name").build();
if(!flag)
{
Gson gson = new Gson();
Type type = new TypeToken<List<String>>() {}.getType();
String json = gson.toJson(notesList, type);
Log.d(TAG, "doInBackground: "+json);
Notes notes = new Notes();
notes.setNoteContent(json);
notes.setUid(1);
dataBase.notesDao().insertNotes(notes);
return notesList;
}
else
{
Gson gson = new Gson();
String notesListContent = dataBase.notesDao().getNotes();
if(dataBase.notesDao().getCount() != 0)
{
notesList = gson.fromJson(notesListContent, new TypeToken<List<String>>()
{
}.getType());
}
else
{
return notesList;
}
return notesList;
}
}
#Override
protected void onPostExecute(List<String> notesList)
{
super.onPostExecute(notesList);
if(flag)
onRead.onRead(notesList);
}
}
}
What's probably happening is that when the dialog returns, it causes a re-layout of the RecyclerView, which rebinds the views. This is prone to bugs though, since it may not have updated the recycler about stuff like the list length or item view types, etc, so the appropriate notify method should always be used.
When you get the text from the dialog to main activity after pressing the positive button.
Append your list with that new text that you are passing to adapter and call method
adapter.notifyDataSetChanged();
I am creating a RecylerView using RecyclerView.Adapter class implementing the Filterable interface. I have checked my code thoroughly but could find the cause of the error. When I use this adapter class in SearcView's setOnQueryTextListener.onQueryTextChange method, it show "Cannot resolve the getFilter() method".
Here is code for custom RecyclerView.Adapter class:
public class CUGAdapter extends RecyclerView.Adapter<CUGAdapter.CUGViewHolder> implements Filterable {
private ArrayList<Contact> CUG;
private ArrayList<Contact> filteredCUG;
public class CUGViewHolder extends RecyclerView.ViewHolder{
public TextView emp_id;
public TextView emp_name;
public TextView emp_designation;
public TextView emp_mobile;
public View layout;
public CUGViewHolder(View v) {
super(v);
this.layout = v;
this.emp_id = (TextView) v.findViewById(R.id.txt_empid);
this.emp_name = (TextView) v.findViewById(R.id.txt_name);
this.emp_designation = (TextView) v.findViewById(R.id.txt_designation);
this.emp_mobile = (TextView) v.findViewById(R.id.txt_mobile);
}
}
public CUGAdapter(ArrayList<Contact> CUG) {
this.CUG = CUG;
}
#Override
public CUGAdapter.CUGViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View v = inflater.inflate(R.layout.listview_layout, parent, false);
CUGViewHolder vh = new CUGViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(CUGViewHolder holder, int position) {
Contact c = filteredCUG.get(position);
holder.emp_mobile.setText(c.mobile);
holder.emp_designation.setText(c.designation);
holder.emp_name.setText(c.name);
holder.emp_id.setText(c.empid);
}
#Override
public int getItemCount() {
return filteredCUG.size();
}
#Override
public Filter getFilter() {
return new Filter() {
private ArrayList<Contact> filtered = new ArrayList<Contact>();
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString().toLowerCase();
filtered.clear();
if(charString.isEmpty()){
filtered = CUG;
//filteredCUG = CUG;
}
else{
for (Contact cug : CUG){
if( cug.name.toLowerCase().contains(charString) || cug.mobile.toLowerCase().contains(charString) || cug.empid.toLowerCase().contains(charString)){
filtered.add(cug);
}
}
//filteredCUG = filtered;
}
FilterResults filterResults = new FilterResults();
filterResults.values = filtered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
//filteredCUG.clear();
filteredCUG = (ArrayList<Contact>) filterResults.values;
notifyDataSetChanged();
}
};
}}
Here is code for searchview listner:
public boolean onCreateOptionsMenu(Menu menu) {
menu.findItem(R.id.app_bar_search).getActionView();
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.app_bar_search).getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);// Error occurs at this line
return false;
}
});
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}}
Change your adapter initialization to
CUGAdapter adapter = new CUGAdapter(this.cuglist);
I'm working on a homework planner app, and I'm looking for a way to display only certain elements in an ArrayList that holds Task objects. After the user clicks on a course from a list of course titles, the list of tasks that pertain to that course should be displayed. Currently, it shows a list of all tasks, no matter which course has been selected. Each Task object stores the course that it belongs to, in a field called mBelongsToCourse. I would like to be able to filter the ArrayList of all tasks that is used in my TaskAdapter to only show the tasks which belong to a specific course, but all my attempts have been fruitless.
Below is my TaskListFragment Class, which includes the TaskAdapter:
public class TaskListFragment extends ListFragment {
private ArrayList<Task> mTasks;
private static String courseName;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
courseName = getActivity().getIntent().getStringExtra("name");
getActivity().setTitle(courseName);
mTasks = TaskLab.get(getActivity()).getTasks();
TaskAdapter adapter = new TaskAdapter(mTasks);
setListAdapter(adapter);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
//Get the Task from the adapter
Task t = ((TaskAdapter)getListAdapter()).getItem(position);
// Start TaskActivity for this task
Intent i = new Intent(getActivity(), TaskActivity.class);
i.putExtra(TaskFragment.EXTRA_TASK_ID, t.getId());
startActivity(i);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_task_list, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_task:
Task task = new Task();
task.setBelongsToCourse(courseName);
TaskLab.get(getActivity()).addTask(task);
Intent i = new Intent(getActivity(), TaskActivity.class);
i.putExtra(TaskFragment.EXTRA_TASK_ID, task.getId());
//i.putExtra("cn", task.getBelongsToCourse());
startActivityForResult(i, 0);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().getMenuInflater().inflate(R.menu.task_list_item_context, menu);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = super.onCreateView(inflater, parent, savedInstanceState);
ListView listView = (ListView)v.findViewById(android.R.id.list);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Required, but not used in this implementation
}
// ActionMode.Callback methods
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.task_list_item_context, menu);
return true;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
// Required, but not used in this implementation
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_delete_task:
TaskAdapter adapter = (TaskAdapter)getListAdapter();
TaskLab taskLab = TaskLab.get(getActivity());
for (int i = adapter.getCount() - 1; i >= 0; i--) {
if (getListView().isItemChecked(i)) {
taskLab.deleteTask(adapter.getItem(i));
}
}
mode.finish();
adapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
public void onDestroyActionMode(ActionMode mode) {
// Required, but not used in this implementation
}
});
return v;
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
int position = info.position;
TaskAdapter adapter = (TaskAdapter)getListAdapter();
Task task = adapter.getItem(position);
switch (item.getItemId()) {
case R.id.menu_item_delete_task:
TaskLab.get(getActivity()).deleteTask(task);
adapter.notifyDataSetChanged();
return true;
}
return super.onContextItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
((TaskAdapter)getListAdapter()).notifyDataSetChanged();
}
private class TaskAdapter extends ArrayAdapter<Task> {
public TaskAdapter(ArrayList<Task> tasks) {
super(getActivity(), 0, tasks);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If we weren't given a view, inflate one
if (convertView == null) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.list_item_task, null);
}
// Configure the view for this Task
Task t = getItem(position);
TextView titleTextView =
(TextView)convertView.findViewById(R.id.task_list_item_titleTextView);
titleTextView.setText(t.getTitle());
TextView dateTextView =
(TextView)convertView.findViewById(R.id.task_list_item_dateTextView);
dateTextView.setText(t.getDate().toString());
CheckBox completedCheckBox =
(CheckBox)convertView.findViewById(R.id.task_list_item_completedCheckBox);
completedCheckBox.setChecked(t.isCompleted());
return convertView;
}
}
}
Any help would be greatly appreciated.
EDIT: I've followed the advice of Ravind Maurya and Embattled Swag and updated my TaskAdapter:
private class TaskAdapter extends ArrayAdapter<Task> implements Filterable {
private ArrayList<Task> taskList;
private Filter taskFilter;
public TaskAdapter(ArrayList<Task> tasks) {
super(getActivity(), 0, tasks);
this.taskList = tasks;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// If we weren't given a view, inflate one
if (convertView == null) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.list_item_task, null);
}
// Configure the view for this Task
Task t = getItem(position);
TextView titleTextView =
(TextView)convertView.findViewById(R.id.task_list_item_titleTextView);
titleTextView.setText(t.getTitle());
TextView dateTextView =
(TextView)convertView.findViewById(R.id.task_list_item_dateTextView);
dateTextView.setText(t.getDate().toString());
CheckBox completedCheckBox =
(CheckBox)convertView.findViewById(R.id.task_list_item_completedCheckBox);
completedCheckBox.setChecked(t.isCompleted());
return convertView;
}
#Override
public Filter getFilter() {
if (taskFilter == null)
taskFilter = new TaskFilter();
return taskFilter;
}
private class TaskFilter extends Filter {
#Override
protected FilterResults performFiltering (CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null | constraint.length() == 0) {
results.values = taskList;
results.count = taskList.size();
} else {
ArrayList<Task> newTaskList = new ArrayList<Task>();
for (Task t : taskList) {
if (t.getBelongsToCourse().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
newTaskList.add(t);
}
}
results.values = newTaskList;
results.count = newTaskList.size();
} return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// Now we have to inform the adapter about the new list filtered
if (results.count == 0)
notifyDataSetInvalidated();
else {
taskList = (ArrayList<Task>)results.values;
notifyDataSetChanged();
}
}
}
}
Now the problem I have is I don't know where to call .getFilter().filter(courseName) in order to filter the ArrayList.
I followed this example literally yesterday to come up with a solid filter: http://www.survivingwithandroid.com/2012/10/android-listview-custom-filter-and.html
However; this example doesn't cover the case where you use the backspace and therefore the listview has to repopulate. You can follow the actual source code for the generic Filter here (it's at the bottom...essentially you'll just create a copy and then reduce the items of one of the lists): http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/widget/ArrayAdapter.java#ArrayAdapter.0mOriginalValues