您的位置:首页 > 移动开发 > Android开发

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

2017-08-25 09:19 961 查看
效果图:



要求: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.s
ab21
etText("在内部存储中");
}

// 处理小标题
// 第一个用户应用和第一个系统应用,显示标题
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: