Android 使用ListView实现列表条目分组展示(两组)小标题悬浮在顶部

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lijinweii/article/details/77547486

效果图:

要求:1.获取手机中的应用,是系统应用还是用户应用。

2.展示两组应用,为两组应用添加小标题。

3.滑动列表,当滑动至顶部时,小标题交替悬浮。

写这个功能前,我也和往常的惯例一样查了一些资料,(滑动组件顶部悬浮固定)我们也参考下:

http://blog.csdn.net/ganshenml/article/details/53112722

http://www.jb51.net/article/110725.htm

http://www.jianshu.com/p/c596f2e6f587

https://yq.aliyun.com/articles/24281

http://blog.csdn.net/u012341052/article/details/52105931

代码片段:

AppUtils.java  获取手机中安装的所有的应用的信息

/**
 * 获得手机中安装的所有的应用的信息
 */
public class AppUtils {

	/**
	 * 获得手机中安装的所有的应用的信息
	 * @param ctx
	 * @return
	 */
	public static List<AppInfoBean> getAllAppInfo(Context ctx){
		List<AppInfoBean> allAppInfo = new ArrayList<AppInfoBean>();
		
		// 包管理器,管理手机 中所有的APK 安装包
		PackageManager pm = ctx.getPackageManager();    //   pm  project manager 项目经理
		
		List<PackageInfo> installedPackages = pm.getInstalledPackages(0);
		for (PackageInfo packageInfo : installedPackages) {
			
			// PackageInfo 包含AndroidManifest清单文件中,所有的信息
			// ApplicationInfo 包含 AndroidManifest清单文件中 , application中的所有的信息
			ApplicationInfo applicationInfo = packageInfo.applicationInfo;
			
			AppInfoBean appBean = new AppInfoBean();
			allAppInfo.add(appBean); // 添加至集合
			
			// 设置包名
			appBean.packageName = packageInfo.packageName;
			
			// 获得应用名称
			appBean.appName = applicationInfo.loadLabel(pm).toString();
			// 应用图标
			appBean.appIcon = applicationInfo.loadIcon(pm);
			
//			applicationInfo.dataDir; // /data/data/包名 路径
			String apkPath = applicationInfo.sourceDir; // 该应用apk 的路径
//			System.out.println(appBean.appName+ " : "+apkPath);
			
			// 为apkPath 赋值
			appBean.apkPath = apkPath;
			
			File apkFile = new File(apkPath);
			appBean.appSize = apkFile.length();
			
			// 根据路径判断是否是系统应用
			if(apkPath.startsWith("/data")){ // 用户应用
				appBean.isSys = false;
				System.out.println(appBean.appName+" 根据 路径 值判断,是用户应用");
			}else{
				// 系统应用
				appBean.isSys = true;
				System.out.println(appBean.appName+" 根据 路径 值判断,是系统应用");
			}
			
			// 根据flag 值来判断是否是系统应用
			// 如果不等于0,说明批配成功,那么当前应用,拥有该 FLAG 值标注的属性
			if((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)!=0 ){ 
				System.out.println(appBean.appName+" 根据 flag 值判断,是系统应用");
			}else{
				System.out.println(appBean.appName+" 根据 flag 值判断,是用户应用");
			}
			
			if((applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0){ //  
				appBean.isInSd = true;
			}else{
				appBean.isInSd = false;
			}
		}
		
		SystemClock.sleep(500); // 休眠2秒,模拟耗时的情况
		
		return allAppInfo;
	}
}

分组展示列表,添加小标题

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="lg.zyqj.zz.listgroup.MainActivity">


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </ListView>

        <TextView
            android:id="@+id/tv_sub_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#aaa"
            android:padding="3dp"
            android:text=""
            android:textColor="#000000" />
    </RelativeLayout>

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private TextView tv_sub_title;
    private List<AppInfoBean> allAppInfo;
    private List<AppInfoBean> userAppList;
    private List<AppInfoBean> sysAppList;
    private MyAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        initListener();
    }

    private void initListener() {

       //为listView 设置滑动的监听
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {

            @Override
            /**
             * 当滑动状态发生改变时,调用
             * @param view
             * @param scrollState
             */
            public void onScrollStateChanged(AbsListView view, int scrollState) {
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

                // 打补丁
                if (userAppList == null) {
                    return;
                }

                // 判断屏幕可见的第一个条目是用户应用,还是系统应用
                int firstPosition = listView.getFirstVisiblePosition(); // 可看到的第一个条目的下标

                if (firstPosition < userAppList.size()) { // 用户应用
                    tv_sub_title.setText("用户应用");
                } else {
                    tv_sub_title.setText("系统应用");
                }
            }
        });
    }

    private void initView() {
        listView = (ListView) findViewById(R.id.listView);
        tv_sub_title = (TextView) findViewById(R.id.tv_sub_title);
    }

    private void initData() {
        userAppList = new ArrayList<AppInfoBean>();//用户应用集合
        sysAppList = new ArrayList<AppInfoBean>();//系统应用集合

        allAppInfo = AppUtils.getAllAppInfo(this);//获取所有应用集合
        for (AppInfoBean app : allAppInfo) {
            if (app.isSys) {
                sysAppList.add(app);
            } else {
                userAppList.add(app);
            }
        }
        adapter = new MyAdapter();
        listView.setAdapter(adapter);
    }

    /**
     * 有会组和标题的listView 实现思路:
     * 1- 展示一个基本的listview
     * 2- 对listView 进行分组
     * 3- 添加小标题
     * 4- 添加固定的标题
     */
    private class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            // listView 的数据,来自于二个集合
            return userAppList.size() + sysAppList.size();
        }

        @Override
        /**
         * 根据position 返回数据Bean
         */
        public Object getItem(int position) {
            // 根据position 获得对应的数据Bean
            AppInfoBean appInfo;//= allAppInfo.get(position);

            if (position < userAppList.size()) {
                // 从用户集合中取数据
                appInfo = userAppList.get(position);
            } else {
                // 从系统集合中取
                appInfo = sysAppList.get(position - userAppList.size());
            }

            return appInfo;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            ViewHolder vh;

            if (convertView == null) {
                view = getLayoutInflater().inflate(R.layout.list_item_app_manager, null);
                vh = new ViewHolder();
                // 找到子view
                ImageView ivIcon = (ImageView) view.findViewById(R.id.iv_icon_list_item);
                TextView tvName = (TextView) view.findViewById(R.id.tv_app_name_list_item);
                TextView tvSize = (TextView) view.findViewById(R.id.tv_app_size_list_item);
                TextView tvLocation = (TextView) view.findViewById(R.id.tv_app_location_list_item);

                TextView tvSubTitle = (TextView) view.findViewById(R.id.tv_sub_title_list_item);
                tvSubTitle.setVisibility(View.GONE);

                // 将子View打包
                vh.ivIcon = ivIcon;
                vh.tvName = tvName;
                vh.tvSize = tvSize;
                vh.tvLocation = tvLocation;

                vh.tvSubTitle = tvSubTitle;
                // 背在view 的身上
                view.setTag(vh);

            } else {
                view = convertView;
                vh = (ViewHolder) view.getTag();
            }

            // 根据position 获得对应的数据Bean
            AppInfoBean appInfo = (AppInfoBean) getItem(position);

            // 为子view 赋值
            vh.ivIcon.setBackgroundDrawable(appInfo.appIcon);

            vh.tvName.setText(appInfo.appName);

            String sizeStr = Formatter.formatFileSize(MainActivity.this, appInfo.appSize);
            vh.tvSize.setText("应用大小:" + sizeStr);

            if (appInfo.isInSd) {
                vh.tvLocation.setText("在SD卡中");
            } else {
                vh.tvLocation.setText("在内部存储中");
            }

            // 处理小标题
            // 第一个用户应用和第一个系统应用,显示标题
            if (position == 0) {
                vh.tvSubTitle.setText("用户应用");
                vh.tvSubTitle.setVisibility(View.VISIBLE);

            } else if (position == userAppList.size()) { // 第一个系统应用

                vh.tvSubTitle.setText("系统应用");
                vh.tvSubTitle.setVisibility(View.VISIBLE);
            } else {
                // 其他情况下,都隐藏标题
                vh.tvSubTitle.setVisibility(View.GONE);
            }

            return view;
        }


        private class ViewHolder {
            public TextView tvSubTitle;
            public TextView tvLocation;
            public TextView tvSize;
            public TextView tvName;
            public ImageView ivIcon;

        }
    }

}
list_item_app_manager.xml

<?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"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_sub_title_list_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#aaa"
        android:padding="3dp"
        android:text="我是小标题"
        android:textColor="#000000" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/iv_icon_list_item"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:background="@drawable/app" />

        <TextView
            android:id="@+id/tv_app_name_list_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:layout_toRightOf="@id/iv_icon_list_item"
            android:text="应用名称"
            android:textColor="#000000" />

        <TextView
            android:id="@+id/tv_app_size_list_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/tv_app_name_list_item"
            android:layout_toRightOf="@id/iv_icon_list_item"
            android:text="应用大小:xxxxM" />

        <TextView
            android:id="@+id/tv_app_location_list_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text="应用位置" />
    </RelativeLayout>

</LinearLayout>

AppInfoBean.java

public class AppInfoBean {

	
	/**
	 * 应用的包名
	 */
	public String packageName;
	
	public String appName;
	
	public Drawable appIcon;
	
	/**
	 * 应用的大小,即APK安装包的大小
	 */
	public long appSize;
	
	/**
	 * 判断是否是安装在SD卡中
	 */
	public boolean isInSd;
	
	/**
	 * 判断是否是系统应用
	 */
	public boolean isSys;
	
	/**
	 * APK文件的路径
	 */
	public String apkPath;
	
}

我就不做过多的解释了,代码中都已注释

源码:http://download.csdn.net/download/lijinweii/9949407


猜你喜欢

转载自blog.csdn.net/lijinweii/article/details/77547486