MultiChoiceModeListener not working - java

I am trying to implement MultiChoiceModeListener for select multiple item from a ListView. My current progress is shown below. But it doesn't working. It has no action on even long press. is any thing missed in my code or anything wrong? Any help will be greatly appreciated.
public class FragmentFavorite extends Fragment {
ListView lvFavoriteItems;
Activity mActivity = null;
Context mContext;
ArrayList<String> names = new ArrayList<>(Arrays.asList("My name is a", "My name is b",
"My name is c", "My name is d", "My name is e", "My name is f"));
ArrayList<String> phone = new ArrayList<>(Arrays.asList("9895653263", "9895653264", "9895653265",
"9895653266", "9895653267", "9895653267"));
#Override
public void onAttach(Context context) {
super.onAttach(context);
if(mActivity == null) {
this.mActivity = getActivity();
}
this.mContext = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.favorite_list, container, false);
lvFavoriteItems = (ListView) root.findViewById(R.id.lv_item_list);
FavoriteAdapter fav = new FavoriteAdapter();
lvFavoriteItems.setAdapter(fav);
lvFavoriteItems.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
lvFavoriteItems.setMultiChoiceModeListener(new FavMultiChoiceModeListener());
return root;
}
private class FavoriteAdapter extends BaseAdapter {
#Override
public int getCount() {
return names.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View listItem;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
listItem = inflater.inflate(R.layout.contact_item_2_line, null);
} else {
listItem = convertView;
}
TextView tv1 = (TextView) listItem.findViewById(R.id.tv_item_name);
tv1.setText(names.get(position));
TextView tv2 = (TextView) listItem.findViewById(R.id.tv_phone);
tv2.setText(phone.get(position));
listItem.setId(position);
return listItem;
} }
private class FavMultiChoiceModeListener implements ListView.MultiChoiceModeListener {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int i, long l, boolean b) {
final int checkedCount = lvFavoriteItems.getCheckedItemCount();
mode.setSubtitle("" + checkedCount + " items selected ");
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = mActivity.getMenuInflater();
inflater.inflate(R.menu.selection_menu, menu);
actionMode.setTitle("Select Items");
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return true;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
Toast.makeText(mActivity, "Clicked " + menuItem.getTitle(),
Toast.LENGTH_SHORT).show();
return true;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
}
}

Since you're extending from BaseAdapter, you might need to call convertView.setLongClickable(true) in your getView method.

Related

get context after returning from adapter to fragment

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.

Android ListView highlighting is not working with BaseAdapter

I have a trouble while creating a ListView with choice mode of CHOICE_MODE_MULTIPLE_MODAL. I added android:background="?android:attr/activatedBackgroundIndicator" in my list item layout. But my problem is the list items not getting highlighted on selection. but action mode shows the number of items selected.
here is my code snippet. if it's not enough please comment.
group_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="?android:attr/activatedBackgroundIndicator">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:textColor="#color/black"
android:textSize="20sp"
android:padding="10dp"
android:id="#+id/tv_item_head"/>
</LinearLayout>
ListViewFragment.java
public class ListViewFragment extends Fragment {
private ArrayList<String> listItems;
ListViewAdapter adapter;
private Activity mActivity;
private ListView listView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_listview, container, false);
initVariables();
if(mActivity == null) {
mActivity = getActivity();
}
listView = (ListView) root.findViewById(R.id.list);
listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new callbacks());
adapter = new ListViewAdapter(listItems, getActivity(), getContext());
listView.setAdapter(adapter);
return root;
}
private void initVariables() {
listItems = new ArrayList<>(Arrays.asList("Item 1", "Item 2", "Item 3", "Item 4", "Item 5","Item 6","Item 7"));
}
private class callbacks implements ListView.MultiChoiceModeListener {
#Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
final int checkedCount = listView.getCheckedItemCount();
mode.setSubtitle("" + checkedCount + " items selected");
adapter.checkedItems.put(position, checked);
adapter.notifyDataSetChanged();
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = mActivity.getMenuInflater();
inflater.inflate(R.menu.list_select_menu, menu);
actionMode.setTitle("Select Items");
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return true;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.share:
Toast.makeText(mActivity, "Shared " + listView.getCheckedItemCount() +
" items", Toast.LENGTH_SHORT).show();
actionMode.finish();
break;
default:
Toast.makeText(mActivity, "Clicked " + menuItem.getTitle(),
Toast.LENGTH_SHORT).show();
break;
}
return true;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
adapter.checkedItems.clear();
adapter.notifyDataSetChanged();
}
}
}
ListViewAdapter.java
public class ListViewAdapter extends BaseAdapter {
ArrayList<String> listItems;
Context mContext;
Activity mActivity;
SparseBooleanArray checkedItems;
public ListViewAdapter(ArrayList<String> listItems, FragmentActivity activity, Context context) {
this.listItems = listItems;
this.mActivity = activity;
this.mContext = context;
this.checkedItems = new SparseBooleanArray();
}
#Override
public int getCount() {
return listItems.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
View listItem;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
listItem = inflater.inflate(R.layout.group_layout, null);
} else {
listItem = convertView;
}
TextView tv = (TextView) listItem.findViewById(R.id.tv_item_head);
tv.setText(listItems.get(position));
listItem.setId(position);
listItem.setActivated(checkedItems.get(position));
return listItem;
}
}
Is any thing missed here. Any help will be greatly appreciated.
Please point out any thing in my code which is not obeying the android convention or rules, if any.

Filtering ListView by SearchView's query - what am I doing wrong?

As the topic's name mentions, I'm facing a problem when I'm trying to implement live ListView filtering, when user enters some text in search bar, which is located in the Action Bar.
P.S. I didn't even hav Log.i("Nomad", "onQueryTextChange") in onQueryTextChange() printed in the log, when I'm debugging the application :/
AllLists.java
public class AllLists extends Fragment implements SearchView.OnQueryTextListener{
private TypedArray navMenuIcons;
private Context context;
private int position = 0;
private String location;
private List<Item> items = new ArrayList<Item>();
private ListView listView;
private CustomListAdapter adapter;
private SearchView mSearchView;
public AllLists(Context context) {
this.context = context;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.alllists, container, false);
View header = inflater.inflate(R.layout.list_header, null);
// View list_view = inflater.inflate(R.layout.list_item, null);
ImageView image = (ImageView) header.findViewById(R.id.small_icon);
header.setClickable(false);
// ImageView logo = (ImageView) list_view.findViewById(R.id.image);
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
Bundle bundle = getArguments();
position = bundle.getInt("position");
location = bundle.getString("location");
image.setImageDrawable(navMenuIcons.getDrawable(position));
DatabaseHandler db = new DatabaseHandler(context);
items = db.getAllItems(location);
listView = (ListView) rootView.findViewById(R.id.list);
adapter = new CustomListAdapter(context, items);
listView.setAdapter(adapter);
listView.addHeaderView(header);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (location.equals("accommodation") || location.equals("eat") || location.equals("events")
|| location.equals("entertainment") || location.equals("places") || location.equals("cinema")) {
Intent i = new Intent(context, ItemScreen.class);
i.putExtra("position", position - 1);
i.putExtra("location", location);
startActivity(i);
}
}
});
setHasOptionsMenu(true);
return rootView;
}
/*SearchView.OnQueryTextListener(new SearchView.OnQueryTextListener){
}*/
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String s) {
adapter.getFilter().filter(s);
return false;
}
});
}
#Override
public boolean onQueryTextChange(String s) {
Log.i("Nomad", "onQueryTextChange");
adapter.getFilter().filter(s);
return false;
}
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
}
CustomListAdapter.java
public class CustomListAdapter extends BaseAdapter {
private Context context;
private List<Item> items;
private LayoutInflater inflater;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
private List<Item> filteredData;
public CustomListAdapter(Context context, List<Item> items) {
this.context = context;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
NetworkImageView image = (NetworkImageView) convertView.findViewById(R.id.image);
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView type = (TextView) convertView.findViewById(R.id.type);
Item i = items.get(position);
// Log.d("FOTO linkas: " + i.getName() + " ", i.getIcon());
if (i.getIcon().contains("http")) {
// Log.d("suveike: ", i.getIcon());
image.setImageUrl(i.getIcon(), imageLoader);
}/*else if(items.get(0).getName().contains("taksi")) {
Log.d("suveike: ", "else if");
image.setImageResource(R.drawable.logo);
}*/ else
image.setImageResource(R.drawable.logo);
name.setText(i.getName());
type.setText(i.getType());
return convertView;
}
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults results = new FilterResults();
if (charSequence == null || charSequence.length() == 0) {
results.values = items;
results.count = items.size();
} else {
List<Item> filtered_items = new ArrayList<Item>();
for (int i = 0; i < items.size(); i++) {
if (items.get(i).getName().contains(charSequence))
filtered_items.add(items.get(i));
}
results.values = filtered_items;
results.count = filtered_items.size();
}
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
filteredData = (List<Item>) filterResults.values;
notifyDataSetChanged();
}
};
}
}
You have to type listView.setAdapter(adapter) after adapter.getFilter().filter(s) in onQueryTextChange. That will refresh the listView.
Well then, you can try this..Don't do implements SearchView.onQueryTextChangeListner..
Instead in onCreateView, write the following
mSearchView.setOnQueryTextListener(new OnQueryTextListener()
{
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
//your code here
return false;
}
});

Add a ListView to a Fragment with Crash

I'm trying to convert my entire ListFragment class into a Fragment class with a ListView added to it.
Call this class HomeworkListFragment. I changed the extension from ListFragment to Fragment:
As a result I have created the following:
public class HomeworkListFragment extends Fragment{
public static final String TAG = "HomeworkListFragment";
public ListView mListView;
public HomeworkAdapter mAdapter;
private ArrayList<HomeworkObject> mCrimes;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
getActivity().setTitle(R.string.homework_title);
mCrimes = HomeworkLab.get(getActivity()).getHomework();
mAdapter = new HomeworkAdapter(mCrimes);
mListView.setAdapter(mAdapter);
setRetainInstance(true);
}
#TargetApi(11)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = super.onCreateView(inflater,parent,savedInstanceState);
mListView = (ListView)v.findViewById(android.R.id.list);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListView.setMultiChoiceModeListener(new MultiChoiceModeListener(){
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.menu_item_delete_homework:
HomeworkLab homeworkLab = HomeworkLab.get(getActivity());
for (int i = mAdapter.getCount() - 1;i>=0;i--){
//if (mListView.getListView().isItemChecked(i)){
//homeworkLab.deleteHomework(mAdapter.getItem(i));
//}
}
mode.finish();
mAdapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//ActionMode.callback Methods
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.homework_list_item_context, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode arg0) {
//not used here
}
#Override
public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
//not used here
return false;
}
#Override
public void onItemCheckedStateChanged(ActionMode arg0,
int arg1, long arg2, boolean arg3) {
//not used here
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
HomeworkObject c = mAdapter.getItem(position);
//Start CrimeActivity
//Intent i = new Intent(getActivity(), CrimeActivity.class);
Intent i = new Intent(getActivity(), HomeworkPagerActivity.class);
i.putExtra(HomeworkFragment.EXTRA_HOMEWORK_ID, c.getId());
startActivity(i);
}
});
return v;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
super.onCreateOptionsMenu(menu,inflater);
inflater.inflate(R.menu.fragment_homework_list, menu);
}
#TargetApi(11)
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.menu_item_new_homework:
HomeworkObject homework = new HomeworkObject();
homework.setTitle("");
HomeworkLab.get(getActivity()).addHomework(homework);
Intent i = new Intent(getActivity(),HomeworkPagerActivity.class);
i.putExtra(HomeworkFragment.EXTRA_HOMEWORK_ID, homework.getId());
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.homework_list_item_context, menu);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
int position = info.position;
HomeworkObject h = mAdapter.getItem(position);
switch (item.getItemId()) {
case R.id.menu_item_delete_homework:
HomeworkLab.get(getActivity()).deleteHomework(h);
mAdapter.notifyDataSetChanged();
return true;
}
return super.onContextItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
mAdapter.notifyDataSetChanged();
mCrimes = HomeworkLab.get(getActivity()).getHomework();//update list
}
#Override
public void onPause(){
super.onPause();
HomeworkLab.get(getActivity()).saveHomework();
}
/*#Override
public void onListItemClick(ListView l, View v, int position, long id){
HomeworkObject c = ((HomeworkAdapter)getListAdapter()).getItem(position);
//Start CrimeActivity
//Intent i = new Intent(getActivity(), CrimeActivity.class);
Intent i = new Intent(getActivity(), HomeworkPagerActivity.class);
i.putExtra(HomeworkFragment.EXTRA_HOMEWORK_ID, c.getId());
startActivity(i);
}*/
private class HomeworkAdapter extends ArrayAdapter<HomeworkObject>{
public HomeworkAdapter(ArrayList<HomeworkObject> crimes){
super(getActivity(), 0, crimes);
}
#SuppressLint("SimpleDateFormat")
#Override
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null){
convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_homework, null);
}
HomeworkObject c = getItem(position);
TextView titleTextView = (TextView)convertView.findViewById(R.id.homework_list_item_titleTextView);
titleTextView.setText(c.getTitle());
TextView dateTextView = (TextView)convertView.findViewById(R.id.homework_list_item_dateTextView);
DateFormat df = new SimpleDateFormat("EEEE, d MMMM yyyy");
String reportDate = df.format(c.getDate());
dateTextView.setText(reportDate);
//dateTextView.setText(c.getDate().toString());
CheckBox solvedCheckBox = (CheckBox)convertView.findViewById(R.id.homework_list_item_solvedCheckBox);
solvedCheckBox.setChecked(c.isSolved());
return convertView;
}
}
}
As far as I can tell there's an error in the onCreateView method with some null pointer error but I can't make heads or tails of this issue.
I recently picked up Android after moving from iOS so I'm pretty new to this. Any explanation could help a lot!
problem:
mListView = (ListView)v.findViewById(android.R.id.list);
The android.R.id.list is only bounded to the ListFragment not in Fragment and that is why it is null.
as the documentation for ListFragment:
ListFragment has a default layout that consists of a single list view.
However, if you desire, you can customize the fragment layout by returning
your own view hierarchy from onCreateView(LayoutInflater, ViewGroup, Bundle).
To do this, your view hierarchy must contain a ListView object with the
id "#android:id/list" (or list if it's in code)
Solution:
You need to inflate a view in your fragment and create a layout with ListView and use the created ID of the ListView instead of android.R.id.list
Use this instead:
#TargetApi(11)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
super.onCreateView(inflater,parent,savedInstanceState);
View v = inflater.inflate(R.layout.my_fragment_layout, parent, false);
mListView = (ListView)v.findViewById(android.R.id.list);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListView.setMultiChoiceModeListener(new MultiChoiceModeListener(){
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.menu_item_delete_homework:
HomeworkLab homeworkLab = HomeworkLab.get(getActivity());
for (int i = mAdapter.getCount() - 1;i>=0;i--){
//if (mListView.getListView().isItemChecked(i)){
//homeworkLab.deleteHomework(mAdapter.getItem(i));
//}
}
mode.finish();
mAdapter.notifyDataSetChanged();
return true;
default:
return false;
}
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//ActionMode.callback Methods
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.homework_list_item_context, menu);
return true;
}
#Override
public void onDestroyActionMode(ActionMode arg0) {
//not used here
}
#Override
public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
//not used here
return false;
}
#Override
public void onItemCheckedStateChanged(ActionMode arg0,
int arg1, long arg2, boolean arg3) {
//not used here
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
HomeworkObject c = mAdapter.getItem(position);
//Start CrimeActivity
//Intent i = new Intent(getActivity(), CrimeActivity.class);
Intent i = new Intent(getActivity(), HomeworkPagerActivity.class);
i.putExtra(HomeworkFragment.EXTRA_HOMEWORK_ID, c.getId());
startActivity(i);
}
});
return v;
}

How to filter ArrayAdapter?

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

Categories

Resources