效果图:
要求: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 getAllAppInfo(Context ctx){
List allAppInfo = new ArrayList();
// 包管理器,管理手机 中所有的APK 安装包
PackageManager pm = ctx.getPackageManager(); // pm project manager 项目经理
List 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
public class MainActivity extends AppCompatActivity {
private ListView listView;
private TextView tv_sub_title;
private List allAppInfo;
private List userAppList;
private List 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();//用户应用集合
sysAppList = new ArrayList();//系统应用集合
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
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