转载请注明出处:https://blog.csdn.net/mythmayor/article/details/72900243
1.应用程序信息的flags
- int flags = packageInfo.applicationInfo.flags
- 0000 0000 0000 0000 0000 0000 0000 0000 //int的32位每一位的0或者1表示一个boolean值
- 适用于需要大量boolean变量的场景,提高效率
具体代码
int flags = packInfo.applicationInfo.flags; if ((flags & ApplicationInfo.FLAG_SYSTEM) != 0) { //系统应用 } else { //用户应用 } if ((flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) { //安装在sd卡 } else { //安装在手机内存 }
2.应用的安装位置
<manifest
... SD卡 手机内存 手机内存
android:installLocation="preferExternal | internalOnly | auto"
/>
3.如何区分显示系统应用和用户应用
- 将“应用程序集合”拆分成“用户程序集合”和“系统程序集合”两个集合
- 在getView方法中,根据position判断,该位置应该是用户程序还是系统程序,在从对应的集合中取出数据
- 注意,当显示第二个集合的数据时,需要对position进行修正
4.将标签加入到ListView的item中显示
- 在getCount中计算出正确的个数:用户程序个数+系统程序个数+标签个数
- 在getView中,根据position判断需要显示的四种类型:用户程序标签、用户程序、系统程序标签、系统程序,根据不同的类型返回不同的view
- 注意,标签是插在列表的前面和中间,需要对position进行修正
5.ListView的item具有多种布局
当我们在Adapter中调用方法getView的时候,如果整个列表中的Item View如果有多种类型布局,如:
我们继续使用convertView来将数据从新填充貌似不可行了,因为每次返回的convertView类型都不一样,无法重用。
Android在设计上的时候,也想到了这点。所以,在adapter中预留的两个方法。
public int getViewTypeCount(); //有多少种布局类型
public int getItemViewType(int position); //获取某个位置是哪种类型类型
只需要重写这两个方法,设置一下ItemViewType的个数和判断方法,Recycler就能有选择性的给出不同的convertView了。
private static final int TYPE_LABEL = 0;
private static final int TYPE_CONTENT = 1;
private class AppManagerAdapter extends BaseAdapter{
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public int getItemViewType(int position) {
if(position == 0 || position == userAappInfos.size()+1){
return TYPE_LABEL;
}else{
return TYPE_CONTENT;
}
}
/**
* 返回listview里面有多少个条目
*/
@Override
public int getCount() {
//为什么要加两个1 , 增加了两个textview的标签。整个listview条目的个数增加了。
return 1+userAappInfos.size()+1+systemAppInfos.size();
}
/**
* 显示每个条目的view对象
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LabelViewHolder labelViewHolder = null;
ContentViewHolder contentViewHolder = null;
int type = getItemViewType(position);
if(convertView == null){
switch (type) {
case TYPE_LABEL:
convertView = new TextView(AppManagerActivity.this);
labelViewHolder = new LabelViewHolder();
labelViewHolder.tv_label = (TextView) convertView;
labelViewHolder.tv_label.setBackgroundColor(Color.GRAY);
convertView.setTag(labelViewHolder);
break;
case TYPE_CONTENT:
convertView = View.inflate(getApplicationContext(), R.layout.item_appinfo, null);
contentViewHolder = new ContentViewHolder();
contentViewHolder.iv_appIcon = (ImageView) convertView.findViewById(R.id.iv_appicon);
contentViewHolder.tv_appName = (TextView) convertView.findViewById(R.id.tv_appName);
contentViewHolder.tv_apkSize = (TextView) convertView.findViewById(R.id.tv_apkSize);
contentViewHolder.iv_install_location = (ImageView) convertView.findViewById(R.id.iv_install_location);
convertView.setTag(contentViewHolder);
break;
}
}else{
switch (type) {
case TYPE_LABEL:
labelViewHolder = (LabelViewHolder) convertView.getTag();
break;
case TYPE_CONTENT:
contentViewHolder = (ContentViewHolder) convertView.getTag();
break;
}
}
switch (type) {
case TYPE_LABEL:
if(position == 0){
labelViewHolder.tv_label.setText("用户程序:"+userAappInfos.size());
}else{
labelViewHolder.tv_label.setText("系统程序:"+systemAppInfos.size());
}
break;
case TYPE_CONTENT:
AppInfo appInfo;
if(position<=userAappInfos.size()){//用户程序
int newPosition = position - 1;//减去用户的标签textview占据的位置
appInfo = userAappInfos.get(newPosition);
}else {//系统程序
int newPosition = position - 1 - userAappInfos.size() - 1;
appInfo = systemAppInfos.get(newPosition);
}
contentViewHolder.iv_appIcon.setImageDrawable(appInfo.getAppIcon());
contentViewHolder.tv_appName.setText(appInfo.getAppName());
contentViewHolder.tv_apkSize.setText("程序大小:"+Formatter.formatFileSize(getApplicationContext(), appInfo.getAppSize()));
if(appInfo.isInRom()){
contentViewHolder.iv_install_location.setImageResource(R.drawable.memory);
}else{
contentViewHolder.iv_install_location.setImageResource(R.drawable.sd);
}
break;
}
return convertView;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
/**
* 存放内容孩子对象的引用
*/
static class ContentViewHolder{
ImageView iv_appIcon;
TextView tv_appName;
TextView tv_apkSize;
ImageView iv_install_location;
}
/**
* 存放标签孩子对象的引用
*/
static class LabelViewHolder{
TextView tv_label;
}
6.ListView的OnScrollListener–滑动监听器
public static int SCROLL_STATE_IDLE = 0; //停止
public static int SCROLL_STATE_TOUCH_SCROLL = 1; //手指拖动
public static int SCROLL_STATE_FLING = 2; //惯性滑动
listView.setonScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//滚动状态发生变化。0停止,1手指拖动,2惯性滑动
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {
//当listview正在滚动的时候调用的方法
//firstVisibleItem:第一个显示的Item的位置
//visibleItemCount:可显示的Item的总数
//totalItemCount:Item的总数
}
});
7.PopupWindow的使用
//创建,指定显示的View和宽高
PopupWindow ppw = new PopupWindow(View contentView, int width, int height);
//显示,parent并不是指要把contentView 添加到parent上,而是要获取token
ppw. showAtLocation(View parent, int gravity, int x, int y);
//关闭
ppw. dismiss();
8.PopupWindow使用注意事项
1.在show之前dismiss掉之前创建的,避免重复显示
2.在Activity的onDestory()的时候dismiss,避免窗体泄漏
9.获取View在Window中的位置
int[] location = new int[2];
view.getLocationInWindow(location);
Location[0]: x坐标
Location[1]: y坐标
获取View在父View中的位置
view.getX();
view.getY();
10.PopupWindow不显示动画的原因
1.手机中设置了动画关闭
2.PopupWindow没有设置背景
注:PopupWindow要设置背景和获取焦点,才能有点击弹框外消失的效果