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.
Related
I'm trying to implement a selection activity for a given list of items. Each item is checkable, so I have an item with a TextView and a CheckBox. I implemented a ListView for displaying all the options and a Spinner for showing only the "Top Ten" choices, as a subset of the same list. For now I'm showing all the items in both ListView and Spinner.
I want for the items in the ListView to update when the user selects an item in the Spinner (Note: The reverse path works fine, as the Spinner grabs the updated ArrayList each time it dropsdown).
I tried to implement setOnItemSelectedListener for my Spinner, and to call notifyOnDataSetChanged() for my ListViewAdapter inside the Listener. But the Listener is only called on collapse and I get a weird (maybe unrelated) warning message.
The onItemSelectedListener for the Spinner only runs when the Spinner gets collapsed. But notifyOnDataSetChanged() seems to ignore the checked status of the items as a change. How can I make the first option run everytime I check an item and have the change get properly received by the ListAdapter?
Here's the Activity.java code:
public class TriageReasonActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triage_reason);
final String[] select_qualification = {
"Select Qualification", "10th / Below", "12th", "Diploma", "UG",
"PG", "Phd"};
Spinner spinner = (Spinner) findViewById(R.id.top_reasons_spinner);
ListView symptoms_list = (ListView) findViewById(R.id.view_list_symptoms);
ArrayList<Symptoms> listVOs = new ArrayList<>();
for (int i = 0; i < select_qualification.length; i++) {
Symptoms reason = new Symptoms();
reason.setTitle(select_qualification[i]);
reason.setSelected(false);
listVOs.add(reason);
}
SymptomsListAdapter mListAdapter = new SymptomsListAdapter(this, 0,
listVOs);
SymptomsSpinnerAdapter mSpinnerAdapter = new SymptomsSpinnerAdapter(this, 0,
listVOs);
symptoms_list.setAdapter(mListAdapter);
spinner.setAdapter(mSpinnerAdapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Log.i("Item selected", "but not cahnged");
symptoms_list.invalidateViews();
mListAdapter.notifyDataSetInvalidated();
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
Log.i("Not item selected", "but actually it did");
}
});
}
The SpinnerCustom Adapter code:
public class SymptomsSpinnerAdapter extends ArrayAdapter<Symptoms>{
private Context mContext;
private ArrayList<Symptoms> listState;
private SymptomsSpinnerAdapter myAdapter;
private boolean isFromView = false;
/*#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//mNotifyOnChange = true;
}*/
public SymptomsSpinnerAdapter(Context context, int resource, List<Symptoms> objects) {
super(context, resource, objects);
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
this.myAdapter = this;
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
}
}
Here's the (almost identical) ListAdapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
private Context mContext;
private ArrayList<Symptoms> listState;
private boolean isFromView = false;
public SymptomsListAdapter(Context context, int resource, List<Symptoms> objects) {
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new SymptomsListAdapter.ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (SymptomsListAdapter.ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
public TextView mTextView;
public CheckBox mCheckBox;
}
}
And here's the warning I'm getting:
W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
EDIT: Adding the layouts and the model class in case they may cause an issue:
Activity Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="demo.hb.activity.visit.TriageReasonActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textFontWeight="6dp"
android:textSize="30sp"
android:layout_margin="20dp"
android:textAlignment="center"
android:textColor="#000000"
android:text="What is the reason for your visit?" />
<Spinner
android:id="#+id/top_reasons_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/btn_dropdown"
android:spinnerMode="dropdown"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/view_list_symptoms"
android:layout_above="#+id/next_btn"
android:layout_alignParentTop="true"/>
</RelativeLayout>
</LinearLayout>
</FrameLayout>
Item layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="text"
android:textAlignment="gravity" />
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" />
</RelativeLayout>
Model Class:
public class Symptoms {
private String title;
private boolean selected;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
The reason that nothing is changing is because you haven't implemented the method to handle the data set changes. You need to handle how the data is reloaded in your adapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
...
public void refreshData(ArrayList<Symptoms> objects){
this.listState = (ArrayList<Symptoms>) objects;
notifyDataSetChanged();
}
...
}
This link does a great job of explaining how the notifyDataSetInvalidated() works (or in your case, why it's not working).
I have stored some value in arraylist if checkbox is clicked but i am having a difficult time to get it from listView class. How can i get it. Also if I keep
clickListener in view that contains checkbox and textView, the checkbox click is not working but if i click in textview it works. How to fix it. Below is my code.
Thanks in advance
singlerow_compare.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:id="#+id/singleRow" android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textViewCompare" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageViewCompare"/>
</RelativeLayout>
listview xml:
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listViewCompare" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Compare"
android:id="#+id/compare"
android:layout_alignParentBottom="true"/>
ListView.java
listView = (HorizontalListView) findViewById(R.id.listViewCompare);
compareBtn = (Button) findViewById(R.id.compare);
listView.setAdapter(new CustomAdapter(this, nameList, imageList));
compareBtn.setOnClickListener(new View.OnClickListener()
{ #Override
public void onClick(View view) {
//I need to have addCheckBoxValue arraylist from adapter here
}
}
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
ArrayList result;
Context context;
Drawable [] imageId;
protected ArrayList<String> addCheckBoxValue;
private static LayoutInflater inflater=null;
public CustomAdapter(CompareListView mainActivity, ArrayList nameList, Drawable[] imageList) {
result=nameList;
context=mainActivity;
imageId=imageList;
inflater = ( LayoutInflater )context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public class Holder
{
TextView tv;
ImageView img;
CheckBox checkBox;
}
#Override
public View getView(final int i, View view, ViewGroup viewGroup) {
addCheckBoxValue = new ArrayList();
final Holder holder=new Holder();
View rowView;
rowView = inflater.inflate(R.layout.singlerow_compare, null);
holder.tv=(TextView) rowView.findViewById(R.id.textViewCompare);
holder.checkBox = (CheckBox) rowView.findViewById(R.id.imageViewCompare);
holder.tv.setText(result.get(i).toString());
holder.checkBox.setButtonDrawable(imageId[i]);
final String selectedCbValue = holder.tv.getText().toString();
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
boolean checked = ((CheckBox) view).isChecked();
if(checked){
if (!addCheckBoxValue.contains(selectedCbValue))
addCheckBoxValue.add(selectedCbValue);
}else{
if (addCheckBoxValue.contains(selectedCbValue))
addCheckBoxValue.remove(selectedCbValue);
}
}
});
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//if i click on textView, it works but when i click on checkbox here, it doesnt work why?? So i have clicklistener in checkbox abov
}
});
return rowView;
}
Create Following method in your CustomAdapter class:
public ArrayList<String> getCheckBoxValue(){
return addCheckBoxValue;
}
And in your ListActivity. Change your activity code like this:
private CustomAdapter listAdapter; // declare this before on create
Now where you are setting adapter in your on create write this code:
listAdapter = new CustomAdapter(this, nameList, imageList)
// set Adapter like this:
listView.setAdapter(listAdapter);
your button on click code should be like this:
compareBtn.setOnClickListener(new View.OnClickListener()
{ #Override
public void onClick(View view) {
//I need to have addCheckBoxValue arraylist from adapter here
listAdapter.getCheckBoxValue(); // do whatever you want to do here
}
}
Happy Coding!!!
I suggest you make boolean array for checkbox and maintain it like this way,this worked for me
public class CustomAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final Context context;
private List<ModelPooja> listData;
public CustomAdapter(Context mainActivity, List<ModelPooja> listData) {
context = mainActivity;
this.listData = listData;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_item_poojaselection, null);
holder.tv = (TextView) convertView.findViewById(R.id.list_item_poojaname);
holder.checks = (CheckBox) convertView.findViewById(R.id.list_item_poojacheck);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
holder.checks.setOnCheckedChangeListener(null);
holder.checks.setFocusable(false);
if (listData.get(position).isselected) {
holder.checks.setChecked(true);
} else {
holder.checks.setChecked(false);
}
holder.checks.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton cb, boolean b) {
if (checkMaxLimit()) {
if (listData.get(position).isselected && b) {
holder.checks.setChecked(false);
listData.get(position).isselected = false;
} else {
holder.checks.setChecked(false);
listData.get(position).isselected = false;
Toast.makeText(context, "Max limit reached", Toast.LENGTH_SHORT).show();
}
} else {
if (b) {
listData.get(position).isselected = true;
} else {
listData.get(position).isselected = false;
}
}
}
});
holder.tv.setText(listData.get(position).getPOOJA_LISTING_NAME());
return convertView;
}
public boolean checkMaxLimit() {
int countermax = 0;
for(ModelPooja item : listData){
if(item.isselected){
countermax++;
}
}
return countermax >= 5;
}
public class ViewHolder {
TextView tv;
public CheckBox checks;
}
}
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.
I need sort alphabetically in my custom ListView. In list_item, I have TextImage and two TextView (app name, package name) and can't understand how sort by alphabet app name:
My list item:
<?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="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal">
<ImageView
android:id="#+id/app_icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:padding="4dp"
android:scaleType="centerCrop"
android:contentDescription="#null"
tools:src="#mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp">
<TextView
android:id="#+id/tv_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="Application name"/>
<TextView
android:id="#+id/tv_app_package"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="app.package.name"/>
</LinearLayout>
</LinearLayout>
And my adapter:
public class ListViewAdapter extends ArrayAdapter{
private Context context;
private List mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, int list_item, List items) {
super(context, R.layout.list_item, items);
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
}
public int getCount(){
return ((null != mItem) ? mItem.size() : 0);
}
#Override
public ApplicationInfo getItem(int position) {
return (null != mItem) ? (ApplicationInfo) mItem.get(position) : null;
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
if (null == view) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
ApplicationInfo data = (ApplicationInfo) mItem.get(position);
if (null != data){
TextView appName = (TextView) view.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) view.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) view.findViewById(R.id.app_icon);
appName.setText(data.loadLabel(packageManager));
appPackage.setText(data.packageName);
icon.setImageDrawable(data.loadIcon(packageManager));
}
return view;
}
}
My fragment in which show ListView
public class ResultFragment extends ListFragment {
private PackageManager packageManager = null;
private ListViewAdapter listViewAdapter = null;
private List mItem;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
packageManager = getContext().getPackageManager();
new LoadApplications().execute();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ApplicationInfo applicationInfo = (ApplicationInfo) mItem.get(position);
try{
Intent intent = packageManager.getLaunchIntentForPackage(applicationInfo.packageName);
if (intent != null){
startActivity(intent);
}
}catch (ActivityNotFoundException e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}catch (Exception e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private List<ApplicationInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList mItem = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
mItem.add(info);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItem;
}
private class LoadApplications extends AsyncTask<Void, Void, Void>{
private ProgressDialog progressDialog = null;
#Override
protected Void doInBackground(Void... params){
mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(getActivity(), R.layout.list_item, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
setListAdapter(listViewAdapter);
progressDialog.dismiss();
super.onPostExecute(result);
}
#Override
protected void onPreExecute(){
progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
super.onPreExecute();
}
}
}
Please help me by sorting my list alphabetically.
From Android Documentation
public abstract android.content.Intent
getLaunchIntentForPackage(java.lang.String packageName)
Returns a
"good" intent to launch a front-door activity in a package. This is
used, for example, to implement an "open" button when browsing through
packages. The current implementation looks first for a main activity
in the category Intent.CATEGORY_INFO, and next for a main activity in
the category Intent.CATEGORY_LAUNCHER. Returns null if neither are
found.
Parameters: packageName - The name of the package to inspect.
Returns: A fully-qualified Intent that can be used to launch the main
activity in the package. Returns null if the package does not contain
such an activity, or if packageName is not recognized.
You need to make some changes in your code
private ArrayList<ResolveInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList<ResolveInfo> mItems = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
Intent intent = packageManager.getLaunchIntentForPackage(info.packageName));
ResolveInfo app = packageManager.resolveActivity(intent,0);
mItems.add(app);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItems;
}
in your asn task
private class LoadApplications extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params){
ArrayList<ResolveInfo> mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(ctx, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
listView.setAdapter(listViewAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ResolveInfo resolveInfo = listViewAdapter.getItem(position);
ActivityInfo activityInfo = resolveInfo.activityInfo;
ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,activityInfo.name);
Intent intent = new Intent();
intent.setComponent(name);
startActivity(intent);
}
});
}
#Override
protected void onPreExecute(){
super.onPreExecute();
//progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
}
}
In your adapter constructor
public class ListViewAdapter extends BaseAdapter {
private Context context;
private ArrayList<ResolveInfo> mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, ArrayList<ResolveInfo> items) {
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
Collections.sort(mItem,new ResolveInfo.DisplayNameComparator(packageManager));
}
public int getCount(){
return mItem.size();
}
#Override
public ResolveInfo getItem(int position) {
return mItem.get(position);
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.testa, null);
}
ResolveInfo app = mItem.get(position);
TextView appName = (TextView) convertView.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) convertView.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) convertView.findViewById(R.id.app_icon);
ActivityInfo activity = app.activityInfo;
appPackage.setText(activity.applicationInfo.packageName);
appName.setText(app.loadLabel(packageManager));
icon.setImageDrawable(app.loadIcon(packageManager));
return convertView;
}
}
Find the entire project At Github
First change The Chinese to pinyin you can use the jar pinyin4j-2.5.0.jar
then maybe you can try this method
Arrays.sort(arrayList,String.CASE_INSENSITIVE_ORDER);
Do this it will work
Create a class comparator like this
public class CustomComparator implements Comparator<ApplicationInfo> {
#Override
public int compare(ApplicationInfo o1, ApplicationInfo o2) {
return o1.loadLabel(packageManager).toString().compareTo(o2.loadLabel(packageManager).toString());
}
}
Now use this class in the Async Task where you are creating the adapter
Collections.sort(mItem, new CustomComparator());
listViewAdapter = new ListViewAdapter(context, mItem);
it will sort your list
Let me know in case of more issue
use this method when you need to sort in listview,
Collections.sort(apps, new Comparator<App>() {
#Override
public int compare(App lhs, App rhs) {
//here getTitle() method return app name...
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
Please try this.
public class MainActivity extends AppCompatActivity {
private ArrayList<UserInfo> userInfos;
private CustomListAdapter customListAdapter;
private ListView customListView;
private String[] names={
"3 Khan",
"2 Ahmed",
"1 Iqbal"
};
private String[] professions={
"Rank 1",
"Rank 2",
"Rank 3"
};
private int[] photos={
R.drawable.sample_5,
R.drawable.sample_1,
R.drawable.sample_6
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar((Toolbar)findViewById(R.id.toolbar));
customListView=(ListView)findViewById(R.id.custom_list_view);
userInfos=new ArrayList<>();
Arrays.sort(names,String.CASE_INSENSITIVE_ORDER);
customListAdapter=new CustomListAdapter(userInfos,this);
customListView.setAdapter(customListAdapter);
getDatas();
customListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "Name : " + names[i] + "\n Profession : " + professions[i], Toast.LENGTH_SHORT).show();
}
});
}
// getting all the datas
private void getDatas(){
for(int count=0;count<names.length;count++){
userInfos.add(new UserInfo(names[count],professions[count],photos[count]));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_option,menu);
MenuItem menuItem=menu.findItem(R.id.search);
SearchView searchView=(SearchView)menuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
newText=newText.toString();
ArrayList<UserInfo> newUserInfos=new ArrayList<>();
for(UserInfo userInfo:userInfos){
String name=userInfo.getName().toLowerCase();
String profession=userInfo.getProfession().toLowerCase();
if(name.contains(newText) || profession.contains(newText)){
newUserInfos.add(userInfo);
}
}
customListAdapter.filterResult(newUserInfos);
customListAdapter.notifyDataSetChanged();
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}```
I have a row which is represented by an image, some text and a CheckBoxes. Whenever I'm trying to use the OnItemClickListener for the rows, the event won't fire up when clicking the CheckBoxes.
I also tried checkbox.onCheckedChangedListener but it gives me Null Pointer at findViewByID. I checked, the ID I am looking for is alright, no typos in there.
I'd like to make usage of this OnItemClickListener so later on I can play with the checkboxes. Any ideas?
Code:
ADAPTER:
public class FilterAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mFilters;
private ArrayList<Integer> mPictures;
private Typeface Bebas, DroidSans;
public FilterAdapter(Context context, ArrayList<String> filters, ArrayList<Integer> pictures) {
this.mContext = context;
this.mFilters = filters;
this.mPictures = pictures;
}
#Override
public int getCount() {
return mFilters.size();
}
#Override
public Object getItem(int position) {
return mFilters.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.category_filter_item, null);
}
DroidSans = Typeface.createFromAsset(mContext.getAssets(), "fonts/DroidSans.ttf");
ImageView filter_img = (ImageView) convertView.findViewById(R.id.category_picture);
TextView filter_category = (TextView) convertView.findViewById(R.id.filter_category);
CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.check_box);
filter_category.setTypeface(DroidSans);
filter_category.setText(mFilters.get(position));
filter_img.setBackgroundResource(mPictures.get(position));
return convertView;
}
}
Class where using the Adapter:
public class CheckinFilters extends Fragment {
private ListView mListView;
private FilterAdapter filterAdapter;
private ArrayList<String> l = new ArrayList<String>();
private ArrayList<Integer> drawables = new ArrayList<Integer>();
private Typeface Bebas;
private ArrayList<Integer> checkboxes = new ArrayList<Integer>();
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
public CheckinFilters() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_checkin_filters, container, false);
l.add("Chill");
l.add("Eat");
l.add("Explore");
l.add("Move");
l.add("Party");
l.add("Whatever");
drawables.add(R.drawable.category_chill);
drawables.add(R.drawable.category_eat);
drawables.add(R.drawable.category_explore);
drawables.add(R.drawable.category_move);
drawables.add(R.drawable.category_party);
drawables.add(R.drawable.category_whatever);
mListView = (ListView) view.findViewById(R.id.filter_list);
filterAdapter = new FilterAdapter(view.getContext(), l, drawables);
mListView.setAdapter(filterAdapter);
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
Bebas = Typeface.createFromAsset(view.getContext().getAssets(), "fonts/BebasNeue.otf");
TextView mainHeader = (TextView) view.findViewById(R.id.filters_text);
mainHeader.setTypeface(Bebas);
SearchView filter_categories = (SearchView) view.findViewById(R.id.filter_categories);
int searchImgID = getResources().getIdentifier("android:id/search_button", null, null);
ImageView searchViewHint = (ImageView) filter_categories.findViewById(searchImgID);
searchViewHint.setImageResource(R.drawable.ab_icon_search);
int searchPlateID = filter_categories.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlateView = filter_categories.findViewById(searchPlateID);
if (searchPlateView != null) {
searchPlateView.setBackgroundResource(R.drawable.search_location_shape);
}
int searchViewID = filter_categories.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView textView = (TextView) filter_categories.findViewById(searchViewID);
textView.setTextColor(Color.GRAY);
CheckBox checkBox = (CheckBox) view.findViewById(R.id.check_box);
return view;
}
private void save() {
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
editor.putInt("first", checkboxes.size());
for (int i = 0; i < checkboxes.size(); i++) {
editor.remove("Status_" + i);
editor.putInt("Status_" + i, checkboxes.get(i));
}
editor.commit();
}
private void load() {
sharedPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
int size = sharedPreferences.getInt("first", 0);
for (int i = 0; i < size; i++) {
checkboxes.add(sharedPreferences.getInt("Status_" + i, 0));
}
}
#Override
public void onPause() {
super.onPause();
save();
}
#Override
public void onResume() {
super.onResume();
load();
}
}
Layout I'm inflating for Adapter:
<?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="match_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ECF0F1">
<ImageView
android:id="#+id/category_picture"
android:layout_width="70dp"
android:layout_height="60dp"
android:background="#drawable/sm_profile"/>
<TextView
android:id="#+id/filter_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/category_picture"
android:padding="10dp"
android:text="Party"
android:textColor="#color/enloop_dark_gray"
android:textSize="18dp"/>
<CheckBox
android:id="#+id/check_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:focusable="false"
android:focusableInTouchMode="false"
android:padding="10dp"/>
</RelativeLayout>
</RelativeLayout>
Instead of using OnItemClickListener in CheckinFilters.java, you should add that code in getView() method of FilterAdapter. You are actually adding checkbox for every row but the id for all checkbox is same, so you can't apply customized code for every checkbox.
To be able to make use of all checkboxes you can put checkbox code in getView() method because it also contains an argument called position. So you can just get the position and apply OnItemClickListener to every single checkbox. That way it will work.
public class FilterAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> mFilters;
private ArrayList<Integer> mPictures;
private Typeface Bebas, DroidSans;
public FilterAdapter(Context context, ArrayList<String> filters, ArrayList<Integer> pictures) {
this.mContext = context;
this.mFilters = filters;
this.mPictures = pictures;
}
#Override
public int getCount() {
return mFilters.size();
}
#Override
public Object getItem(int position) {
return mFilters.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater)
mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.category_filter_item, null);
}
DroidSans = Typeface.createFromAsset(mContext.getAssets(), "fonts/DroidSans.ttf");
ImageView filter_img = (ImageView) convertView.findViewById(R.id.category_picture);
TextView filter_category = (TextView) convertView.findViewById(R.id.filter_category);
CheckBox checkBox = (CheckBox) convertView.findViewById(R.id.check_box);
filter_category.setTypeface(DroidSans);
filter_category.setText(mFilters.get(position));
filter_img.setBackgroundResource(mPictures.get(position));
if(position == 0) {
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
else {
}
}
});
}
//Similarly add OnClickListener to other checkboxes.
return convertView;
}
}