类型提示的item让他一直显示,这里需要帧布局来实现它
在activity_appmanage里添上
<FrameLayout android:layout_width="fill_parent"android:layout_height="wrap_content"><ListViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/lv_appmanage_appinfolist"/><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:background="#798091"android:textColor="#FFFFFF"android:textSize="15sp"android:id="@+id/tv_appmanage_class"/></FrameLayout>
在遇到分界线的时候,能自动改变,如上,需要ID,list有一个onScroll的listener
sys_appinfolist= new ArrayList<AppInfo>(); lv_appmanage_appinfolist.setOnScrollListener(new OnScrollListener(){@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {// TODO Auto-generated method stub}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// TODO Auto-generated method stub}});new MyAsyncTask(){
这里需要第二个方法
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {// 向下拉动,"用户app"将要遇到"系统app","系统app"在划出去的瞬间,"用户"变"系统"if (firstVisibleItem>user_appinfolist.size()+1) {tv_appmanage_class.setText("系统程序("+sys_appinfolist.size()+")个"); }else {//往回滑动,还能变回来tv_appmanage_class.setText("用户程序("+user_appinfolist.size()+")个"); }}
OK 来实现功能
点击一个程序之后能弹出一个功能框,卸载启动分享等
需要listview的onclick
lv_appmanage_appinfolist.setOnItemClickListener(new OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {// TODO Auto-generated method stub} });new MyAsyncTask(){
这里希望能变动位置,所以不宜用alertdialog,改用popup window 弹出框,可以指定显示位置
PopupWindow的第一个参数需要一个view
现以一个textview来示例下
TextView tv = new TextView(AppManagementActivity.this);tv.setText("popup window");tv.setBackgroundColor(Color.RED); PopupWindow pw = new PopupWindow(tv,60,60);pw.showAtLocation(parent, Gravity.LEFT|Gravity.TOP, 0, 0);
这里位置需要通过onItemClick传进来的view获取,这个view就是其中的每个item,view里包含各种信息
//获取当前点击的item的位置坐标int[] location = new int[2];view.getLocationInWindow(location);PopupWindow pw = new PopupWindow(tv,60,60);pw.showAtLocation(parent, Gravity.LEFT|Gravity.TOP, location[0], location[1]);
这样子走起,多次点击的话,之前的不会消失,改之,每次点击不是new,而是只会有一个,成员变量后再判断是否初始化过
int[] location = new int[2];view.getLocationInWindow(location);if(pw == null){pw = new PopupWindow(tv,60,60);}else{pw.dismiss();} pw.showAtLocation(parent, Gravity.LEFT|Gravity.TOP, location[0], location[1]); }
滑动消失
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if(pw!=null){pw.dismiss();pw = null;}
OK
原本的textview换成自定义的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="60dp"android:orientation="horizontal" android:background="@drawable/local_popup_bg"android:padding="5dp"><LinearLayout android:id="@+id/ll_popupwindow_uninstall"android:layout_height="wrap_content"android:layout_width="0dp"android:layout_weight="1"android:paddingLeft="8dp"android:orientation="vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/img1"></ImageView>><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="卸载"></TextView></LinearLayout><LinearLayout android:id="@+id/ll_popupwindow_launch" android:layout_height="wrap_content"android:layout_width="0dp"android:layout_weight="1"android:orientation="vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/img2"> </ImageView><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="启动"></TextView></LinearLayout><LinearLayout android:id="@+id/ll_popupwindow_share"android:layout_height="wrap_content"android:layout_width="0dp"android:layout_weight="1"android:orientation="vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/img3"></ImageView><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="分享"></TextView></LinearLayout>>
</LinearLayout>
View v = View.inflate(getApplicationContext(), R.layout.popupwindow_appmanage, null);int[] location = new int[2];view.getLocationInWindow(location);if(pw == null){pw = new PopupWindow(v,-2,60);}else{pw.dismiss();} //位置上需要优化,加一个50pw.showAtLocation(parent, Gravity.LEFT|Gravity.TOP, location[0]+50, location[1]);
为了用户在点击功能按钮时感应面大一点,在设置id时对LinearLayout点击
然后找到控件
View v = View.inflate(getApplicationContext(), R.layout.popupwindow_appmanage, null);LinearLayout ll_popupwindow_uninstall = (LinearLayout) v.findViewById(R.id.ll_popupwindow_uninstall);LinearLayout ll_popupwindow_launch = (LinearLayout) v.findViewById(R.id.ll_popupwindow_launch);LinearLayout ll_popupwindow_share = (LinearLayout) v.findViewById(R.id.ll_popupwindow_share);
设置监听事件,让activity去实现onclicklistener,这里是view的
public class AppManagementActivity extends Activity implements OnClickListener{
ll_popupwindow_uninstall.setOnClickListener(AppManagementActivity.this);ll_popupwindow_launch.setOnClickListener(AppManagementActivity.this);ll_popupwindow_share.setOnClickListener(AppManagementActivity.this);
<pre name="code" class="java">@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()){case R.id.ll_popupwindow_launch:launch();break;case R.id.ll_popupwindow_share:share();break;case R.id.ll_popupwindow_uninstall:uninstall();break;default:break;}}
完成对应方法
注意在卸载时,要卸载的是点击了的item的APP,需要拿到他的包名,这就需要在点击item的listener那拿到相关信息,这样对应的在bean和工具类里有packagename
//点击item时就能把他的信息存到这个成员变量,方便拿到包名什么的,卸载要用到private AppInfo appinfo_click;
@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {//点击时拿到item信息,卸载要用if (position< user_appinfolist.size()+1) {appinfo_click = user_appinfolist.get(position-1);}else {appinfo_click = sys_appinfolist.get(position-user_appinfolist.size()-2);}
卸载后要让listView刷新UI,其实就是要调用异步方法MyAsyncTask,将它抽成一个函数,本身跳转时要带参数
refreshData(); }private void refreshData() {new MyAsyncTask(){@Overridepublic void pretast() {// TODO Auto-generated method stub}@Overridepublic void intask() {// TODO Auto-generated method stub//adapter需要数据//耗时操作放在子线程appinfolist = GetAppInfosUtils.getAppInfos(AppManagementActivity.this);for(AppInfo appInfo : appinfolist){if(appInfo.is_userprocess){user_appinfolist.add(appInfo);}else{sys_appinfolist.add(appInfo);}}}@Overridepublic void posttast() {// TODO Auto-generated method stubadapter = new MyAdapter();lv_appmanage_appinfolist.setAdapter(new MyAdapter());}}.execute();}
private void uninstall() {// TODO Auto-generated method stubIntent intent = new Intent();intent.setAction("android.intent.action.DELETE");//要获取当前item代表的app的包名,需要在bean里加上packagename,工具类里也要加上intent.setData(Uri.parse("package:"+appinfo_click.getPackagename()));//删除后能给使listview更新一下startActivityForResult(intent,100);}//卸载后刷新UI@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubrefreshData();super.onActivityResult(requestCode, resultCode, data);}
这么写有一个问题,在refresh时起了一个线程,而同时下面的super也使页面重新加载了,但这里线程还未完成,这边重新加载的还是之前的,相当于是resume回来的,所以list显示的APP还在
两点:
1.在异步工具的posttast里应该有一个判断,notify data has changed
2.在refresh前应该统统clean一遍,不清空的话,还执行了异步里的add,元数据不变,在最后面添加了刷新后的数据
@Overridepublic void posttast() {// TODO Auto-generated method stubif(adapter == null){adapter = new MyAdapter();lv_appmanage_appinfolist.setAdapter(new MyAdapter());}else{adapter.notifyDataSetChanged();} }
//卸载后刷新UI@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stub<span style="color:#ff0000;">appinfolist.clear();user_appinfolist.clear();sys_appinfolist.clear();</span>refreshData();super.onActivityResult(requestCode, resultCode, data);}
当然这里也可以不用refresh,而是list里remove掉,notify下,让adapter重新加载,更高效
另外还要判断下,系统APP不能卸载,还有软件管家自己不应该能被删掉
private void uninstall() {// 判断时最好用函数,而不是他的一个成员变量,不规范if (appinfo_click.<span style="color:#ff0000;">isIs_userprocess()</span>){if("com.rjl.mobilephonemanager".equals(appinfo_click.getPackagename())) {Toast.makeText(getApplicationContext(), "一定要删我俺吗,好可怜", 0).show();return;}Intent intent = new Intent();intent.setAction("android.intent.action.DELETE");//要获取当前item代表的app的包名,需要在bean里加上packagename,工具类里也要加上intent.setData(Uri.parse("package:"+appinfo_click.getPackagename()));//删除后能给使listview更新一下startActivityForResult(intent,100);}else{Toast.makeText(getApplicationContext(), "系统应用无法删除", 0).show();} }
在一个APP里启动另一个APP:
private void launch() {// TODO Auto-generated method stubIntent it= getPackageManager().getLaunchIntentForPackage(appinfo_click.getPackagename()); startActivity(it);}
还有个问题,在退出时,没有把popup window销毁掉,他是挂载listView下的,list销毁了他没毁,会报错
@Overrideprotected void onDestroy() {// TODO Auto-generated method stub if (pw!=null) {pw.dismiss();pw=null;}super.onDestroy();}
分享功能:
private void share() {// 这里分享到短信了,没有装微信什么额Intent intent = new Intent();intent.setAction("android.intent.action.SEND");intent.setType("text/plain");intent.putExtra(Intent.EXTRA_TEXT, "推荐您一款应用程序" + appinfo_click.getAppname()+ "下载地址http://www.market.com/id=123");startActivity(intent);}
如果分享到别的APP,要在他的manifest注册先,声明我要接受,比如写一个sinashare的APP,这样在点击分享时就能多出这个APP的选项
<intent-filter><action android:name="android.intent.action.SEND"/><category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> </intent-filter>
<TextViewandroid:id="@+id/helloworld"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/hello_world" />
ublic class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = getIntent();String data = intent.getStringExtra(Intent.EXTRA_TEXT);TextView tv = (TextView) findViewById(R.id.helloworld);tv.setText(data);}
显示可用空间
在activity_appmanage里加上一个LinearLayout
<LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:id="@+id/tv_appmanage_rom"android:text="手机可以用空间 \n100M"android:gravity="center"android:paddingTop="5dp"android:paddingBottom="5dp"> </TextView> <TextViewandroid:layout_width="0dp"android:layout_weight="1"android:layout_height="wrap_content"android:id="@+id/tv_appmanage_sdcard"android:text="SD卡可以用空间 \n100M"android:gravity="center"android:paddingTop="5dp"android:paddingBottom="5dp"> </TextView> </LinearLayout>
声明、找到,oncreate里加上获取的方法
<pre name="code" class="java">private TextView tv_appmanage_rom;private TextView tv_appmanage_sdcard;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_appmanage);lv_appmanage_appinfolist = (ListView) findViewById(R.id.lv_appmanage_appinfolist);tv_appmanage_rom = (TextView) findViewById(R.id.tv_appmanage_rom);tv_appmanage_sdcard = (TextView) findViewById(R.id.tv_appmanage_sdcard);//获得当前SD卡和内存空间的剩余容量,并显示出来calcutorFreeMemoery();
在工具里面加上具体的实现逻辑
public static long getSDcardFreemome(){ long blockSize;long totalBlocks;long availableBlocks;File path = Environment.getExternalStorageDirectory();StatFs stat = new StatFs(path.getPath());// 第二步,通过StatFs获取文件系统相关属性(After API18)//如果用户的版本是高于api18的 就用上面的,否则就用下面的apiif (Build.VERSION.SDK_INT >Build.VERSION_CODES.JELLY_BEAN_MR2) {blockSize = stat.getBlockSizeLong();totalBlocks = stat.getBlockCountLong();availableBlocks = stat.getAvailableBlocksLong();}else {blockSize = stat.getBlockSize();totalBlocks = stat.getBlockCount();availableBlocks = stat.getAvailableBlocks(); }//返回的是sd卡的可用空间return availableBlocks*blockSize;}public static long getRomFreemome(){ long blockSize;long totalBlocks;long availableBlocks;File path = Environment.getDataDirectory(); StatFs stat = new StatFs(path.getPath()); // 第二步,通过StatFs获取文件系统相关属性(After API18)//如果用户的版本是高于api18的 就用上面的,否则就用下面的apiif (Build.VERSION.SDK_INT >Build.VERSION_CODES.JELLY_BEAN_MR2) {blockSize = stat.getBlockSizeLong();totalBlocks = stat.getBlockCountLong();availableBlocks = stat.getAvailableBlocksLong();}else {blockSize = stat.getBlockSize();totalBlocks = stat.getBlockCount();availableBlocks = stat.getAvailableBlocks(); } //返回的是rom的可用空间return availableBlocks*blockSize;}
完成calcutorFreeMemoery方法
private void calcutorFreeMemoery() {// TODO Auto-generated method stub long sdavail = GetAppInfosUtils.getSDcardFreemome(); //bytelong romavail = GetAppInfosUtils.getRomFreemome() ;//tv_appmanage_rom.setText();tv_appmanage_rom.setText("ROM的剩余空间\n"+formatSize(romavail));tv_appmanage_sdcard.setText("SD卡的剩余空间\n"+formatSize(sdavail));}//计算,byte转一下private String formatSize(long size) {return Formatter.formatFileSize(this, size);}