Search code examples
javaandroidsortinglistviewandroid-listview

How to sort alphabetically in custom ListView


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.


Solution

  • 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;
        }
    }
    

    helping

    Find the entire project At Github