手机卫士day11
day11
- 系統(tǒng)進(jìn)程顯示和隱藏- 創(chuàng)建進(jìn)程管理設(shè)置頁(yè)面:ProcessManagerSettingActivity- 編寫設(shè)置頁(yè)面布局文件- 監(jiān)聽(tīng)Checkbox的勾選事件,更新本地SharePreference// 根據(jù)本地記錄,更新checkbox狀態(tài)boolean showSystem = mPrefs.getBoolean("show_system_process", true);if (showSystem) {cbShowSystem.setChecked(true);cbShowSystem.setText("顯示系統(tǒng)進(jìn)程");} else {cbShowSystem.setChecked(false);cbShowSystem.setText("不顯示系統(tǒng)進(jìn)程");}// 設(shè)置狀態(tài)勾選監(jiān)聽(tīng)cbShowSystem.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {if (isChecked) {cbShowSystem.setText("顯示系統(tǒng)進(jìn)程");mPrefs.edit().putBoolean("show_system_process", true).commit();} else {cbShowSystem.setText("不顯示系統(tǒng)進(jìn)程");mPrefs.edit().putBoolean("show_system_process", false).commit();}}});- 根據(jù)sp記錄的是否顯示系統(tǒng)進(jìn)程,更新listview的顯示個(gè)數(shù)@Overridepublic int getCount() {// 通過(guò)判斷是否顯示系統(tǒng)進(jìn)程,更新list的數(shù)量boolean showSystem = mPrefs.getBoolean("show_system_process", true);if (showSystem) {return 1 + mUserProcessList.size() + 1 + mSystemProcessList.size();} else {return 1 + mUserProcessList.size();}}- 保證勾選框改變后,listview可以立即刷新public void setting(View view) {startActivityForResult(new Intent(this,ProcessManagerSettingActivity.class), 0);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// 當(dāng)從設(shè)置頁(yè)面回跳回來(lái)之后,刷新listviewmAdapter.notifyDataSetChanged();}- 鎖屏清理- 演示金山進(jìn)程管理效果- 后臺(tái)啟動(dòng)服務(wù),監(jiān)聽(tīng)廣播//判斷鎖屏清理的廣播是否正在運(yùn)行boolean serviceRunning = ServiceStatusUtils.isServiceRunning("com.itheima.mobilesafeteach.service.AutoKillService", this);if (serviceRunning) {cbLockClear.setChecked(true);cbLockClear.setText("當(dāng)前狀態(tài):鎖屏清理已經(jīng)開(kāi)啟");} else {cbLockClear.setChecked(false);cbLockClear.setText("當(dāng)前狀態(tài):鎖屏清理已經(jīng)關(guān)閉");}cbLockClear.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {Intent intent = new Intent(ProcessManagerSettingActivity.this,AutoKillService.class);if (isChecked) {// 啟動(dòng)鎖屏清理的服務(wù)startService(intent);cbLockClear.setText("當(dāng)前狀態(tài):鎖屏清理已經(jīng)開(kāi)啟");} else {// 關(guān)閉鎖屏清理的服務(wù)stopService(intent);cbLockClear.setText("當(dāng)前狀態(tài):鎖屏清理已經(jīng)關(guān)閉");}}});-------------------------------------/*** 鎖屏清理進(jìn)程的服務(wù)* * @author Kevin* */public class AutoKillService extends Service {private InnerScreenOffReceiver mReceiver;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();//監(jiān)聽(tīng)屏幕關(guān)閉的廣播, 注意,該廣播只能在代碼中注冊(cè),不能在清單文件中注冊(cè)mReceiver = new InnerScreenOffReceiver();IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(mReceiver, filter);}@Overridepublic void onDestroy() {super.onDestroy();unregisterReceiver(mReceiver);mReceiver = null;}/*** 鎖屏關(guān)閉的廣播接收者* * @author Kevin* */class InnerScreenOffReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("屏幕關(guān)閉...");// 殺死后臺(tái)所有運(yùn)行的進(jìn)程ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) {// 跳過(guò)手機(jī)衛(wèi)士的服務(wù)if (runningAppProcessInfo.processName.equals(ctx.getPackageName())) {return;}am.killBackgroundProcesses(runningAppProcessInfo.processName);}}}}- 定時(shí)器清理(介紹)// 在AutoKillService的onCreate中啟動(dòng)定時(shí)器,定時(shí)清理任務(wù)mTimer = new Timer();mTimer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("5秒運(yùn)行一次!");}}, 0, 5000);@Overrideprotected void onDestroy() {super.onDestroy();mTimer.cancel();mTimer = null;}桌面Widget(窗口小部件)
- widget介紹(Android, 瑞星,早期word)
- widget谷歌文檔查看(API Guide->App Components->App Widget)
widget開(kāi)發(fā)流程
1. 在com.itheima.mobilesafe.receiver目錄下創(chuàng)建MyWidget并且繼承AppWidgetProvider 2. 在功能清單文件注冊(cè),參照文檔<receiver android:name=".receiver.MyWidget" ><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/appwidget_info" /></receiver>3. 在res/xml/創(chuàng)建文件example_appwidget_info.xml拷貝文檔內(nèi)容<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp"//能被調(diào)整的最小寬高,若大于minWidth minHeight 則忽略 android:updatePeriodMillis="86400000"//更新周期,毫秒,最短默認(rèn)半小時(shí) android:previewImage="@drawable/preview"//選擇部件時(shí) 展示的圖像,3.0以上使用,默認(rèn)是ic_launcher android:initialLayout="@layout/example_appwidget"//布局文件android:configure="com.example.android.ExampleAppWidgetConfigure"//添加widget之前,先跳轉(zhuǎn)到配置的activity進(jìn)行相關(guān)參數(shù)配置,這個(gè)我們暫時(shí)用不到 android:resizeMode="horizontal|vertical"//widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以豎直拉伸android:widgetCategory="home_screen|keyguard"//分別在屏幕主頁(yè)和鎖屏狀態(tài)也能顯示(4.2+系統(tǒng)才支持)android:initialKeyguardLayout="@layout/example_keyguard"//鎖屏狀態(tài)顯示的樣式(4.2+系統(tǒng)才支持)></appwidget-provider>4. 精簡(jiǎn)example_appwidget_info.xml文件,最終結(jié)果:<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="294dp" android:minHeight="72dp"android:updatePeriodMillis="1800000"android:initialLayout="@layout/appwidget"></appwidget-provider>5. widget布局文件:appwidget.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="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#f00"android:text="我是widget,哈哈哈"android:textSize="30sp" /></LinearLayout>簡(jiǎn)單演示,高低版本對(duì)比
仿照金山widget效果, apktool反編譯,抄金山布局文件(業(yè)內(nèi)抄襲成風(fēng))
1. 反編譯金山apk使用apktool,可以查看xml文件內(nèi)容apktool d xxx.apk 2. 在金山清單文件中查找 APPWIDGET_UPDATE, 找到widget注冊(cè)的代碼 3. 拷貝金山widget的布局文件process_widget_provider.xml到自己的項(xiàng)目中 4. 從金山項(xiàng)目中拷貝相關(guān)資源文件,解決報(bào)錯(cuò) 5. 運(yùn)行,查看效果widget生命周期
/*** 窗口小部件widget* * @author Kevin* */ public class MyWidget extends AppWidgetProvider {/*** widget的每次變化都會(huì)調(diào)用onReceive*/@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);System.out.println("MyWidget: onReceive");}/*** 當(dāng)widget第一次被添加時(shí),調(diào)用onEnable*/@Overridepublic void onEnabled(Context context) {super.onEnabled(context);System.out.println("MyWidget: onEnabled");}/*** 當(dāng)widget完全從桌面移除時(shí),調(diào)用onDisabled*/@Overridepublic void onDisabled(Context context) {super.onDisabled(context);System.out.println("MyWidget: onDisabled");}/*** 新增widget時(shí),或者widget更新時(shí),調(diào)用onUpdate* 更新時(shí)間取決于xml中配置的時(shí)間,最短為半小時(shí)*/@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager,int[] appWidgetIds) {super.onUpdate(context, appWidgetManager, appWidgetIds);System.out.println("MyWidget: onUpdate");}/*** 刪除widget時(shí),調(diào)onDeleted*/@Overridepublic void onDeleted(Context context, int[] appWidgetIds) {super.onDeleted(context, appWidgetIds);System.out.println("MyWidget: onDeleted");}/*** 當(dāng)widget大小發(fā)生變化時(shí),調(diào)用此方法*/@Overridepublic void onAppWidgetOptionsChanged(Context context,AppWidgetManager appWidgetManager, int appWidgetId,Bundle newOptions) {System.out.println("MyWidget: onAppWidgetOptionsChanged");}}定時(shí)更新widget
問(wèn)題: 我們需要通過(guò)widget實(shí)時(shí)顯示當(dāng)前進(jìn)程數(shù)和可用內(nèi)存,但widget最短也得半個(gè)小時(shí)才會(huì)更新一次, 如何才能間隔比較短的時(shí)間來(lái)及時(shí)更新?查看金山日志:當(dāng)桌面有金山widget時(shí), 金山會(huì)在后臺(tái)啟動(dòng)service:ProcessService,并定時(shí)輸出如下日志: 03-29 08:43:03.070: D/MoSecurity.ProcessService(275): updateWidget該日志在鎖屏狀態(tài)下也一直輸出.解決辦法: 后臺(tái)啟動(dòng)service,UpdateWidgetService, 并在service中啟動(dòng)定時(shí)器來(lái)控制widget的更新更新widget方法
/*** 定時(shí)更新widget的service* * @author Kevin* */ public class UpdateWidgetService extends Service {private Timer mTimer;private AppWidgetManager mAWM;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();mAWM = AppWidgetManager.getInstance(this);// 啟動(dòng)定時(shí)器,每個(gè)5秒一更新mTimer = new Timer();mTimer.schedule(new TimerTask() {@Overridepublic void run() {System.out.println("更新widget啦!");updateWidget();}}, 0, 5000);}/*** 更新widget*/private void updateWidget() {// 初始化遠(yuǎn)程的view對(duì)象RemoteViews views = new RemoteViews(getPackageName(),R.layout.process_widget);views.setTextViewText(R.id.tv_running_processes, "正在運(yùn)行的軟件:"+ ProcessInfoProvider.getRunningProcessNum(this));views.setTextViewText(R.id.tv_memory_left,"可用內(nèi)存:"+ Formatter.formatFileSize(this,ProcessInfoProvider.getAvailMemory(this)));// 初始化組件ComponentName provider = new ComponentName(this, MyWidget.class);// 更新widgetmAWM.updateAppWidget(provider, views);}@Overridepublic void onDestroy() {super.onDestroy();mTimer.cancel();mTimer = null;} }-----------------------------啟動(dòng)和銷毀service的時(shí)機(jī)分析widget的聲明周期,在onEnabled和onUpdate中啟動(dòng)服務(wù), 在onDisabled中結(jié)束服務(wù)注意: APK安裝在sd卡上,widget在窗口小部件列表里無(wú)法顯示。 android:installLocation=”preferExternal”, 修改過(guò)來(lái)后,需要卸載,再去安裝widget才生效;
點(diǎn)擊事件處理
// 初始化延遲意圖,pending是等待的意思 Intent intent = new Intent(this, HomeActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);// 當(dāng)點(diǎn)擊widget布局時(shí),跳轉(zhuǎn)到主頁(yè)面 views.setOnClickPendingIntent(R.id.ll_root, pendingIntent);//當(dāng)一鍵清理被點(diǎn)擊是,發(fā)送廣播,清理內(nèi)存 Intent btnIntent = new Intent(); btnIntent.setAction("com.itheima.mobilesafeteach.KILL_ALL"); PendingIntent btnPendingIntent = PendingIntent.getBroadcast(this, 0,btnIntent, PendingIntent.FLAG_UPDATE_CURRENT); views.setOnClickPendingIntent(R.id.btn_clear, btnPendingIntent);--------------------------- /*** 殺死后臺(tái)進(jìn)程的廣播接受者* 清單文件中配置action="com.itheima.mobilesafeteach.KILL_ALL"* * @author Kevin* */ public class KillAllReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("kill all...");// 殺死后臺(tái)所有運(yùn)行的進(jìn)程ProcessInfoProvider.killAll(context);} }---------------------------<receiver android:name=".receiver.KillAllReceiver" ><intent-filter><action android:name="com.itheima.mobilesafeteach.KILL_ALL" /></intent-filter></receiver>做一個(gè)有情懷的程序員, 拒絕耗電!
當(dāng)鎖屏關(guān)閉時(shí),停止widget定時(shí)器的更新UpdateWidgetService:// 注冊(cè)屏幕開(kāi)啟和關(guān)閉的廣播接受者 mReceiver = new InnerScreenReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); registerReceiver(mReceiver, filter);/*** 屏幕關(guān)閉和開(kāi)啟的廣播接收者* * @author Kevin* */ class InnerScreenReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (Intent.ACTION_SCREEN_OFF.equals(action)) {// 屏幕關(guān)閉if (mTimer != null) {// 停止定時(shí)器mTimer.cancel();mTimer = null;}} else {// 屏幕開(kāi)啟startTimer();}} }
程序鎖
- 高級(jí)工具中添加程序鎖入口
- 新建程序鎖頁(yè)面 AppLockActivity
程序鎖頁(yè)面布局文件實(shí)現(xiàn)
activity_app_lock.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="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:orientation="horizontal" ><TextViewandroid:id="@+id/tv_unlock"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tab_left_pressed"android:gravity="center"android:text="未加鎖"android:textColor="#fff" /><TextViewandroid:id="@+id/tv_locked"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tab_right_default"android:gravity="center"android:text="已加鎖"android:textColor="#fff" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_unlock"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="未加鎖軟件:x個(gè)"android:textColor="#000" /><ListViewandroid:id="@+id/lv_unlock"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_locked"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:visibility="gone" ><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="已加鎖軟件:x個(gè)"android:textColor="#000" /><ListViewandroid:id="@+id/lv_locked"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout></LinearLayout>點(diǎn)擊標(biāo)簽切換頁(yè)面
@Override public void onClick(View v) {switch (v.getId()) {case R.id.tv_unlock:// 展示未加鎖頁(yè)面,隱藏已加鎖頁(yè)面llLocked.setVisibility(View.GONE);llUnlock.setVisibility(View.VISIBLE);tvUnlock.setBackgroundResource(R.drawable.tab_left_pressed);tvLocked.setBackgroundResource(R.drawable.tab_right_default);break;case R.id.tv_locked:// 展示已加鎖頁(yè)面,隱藏未加鎖頁(yè)面llUnlock.setVisibility(View.GONE);llLocked.setVisibility(View.VISIBLE);tvUnlock.setBackgroundResource(R.drawable.tab_left_default);tvLocked.setBackgroundResource(R.drawable.tab_right_pressed);break;default:break;} }應(yīng)用列表信息展現(xiàn)(展現(xiàn)全部應(yīng)用列表數(shù)據(jù))
使用數(shù)據(jù)庫(kù)保存已加鎖的軟件
AppLockOpenHelper.java// 創(chuàng)建表, 兩個(gè)字段,_id, packagename(應(yīng)用包名) db.execSQL("create table applock (_id integer primary key autoincrement, packagename varchar(50))");----------------------------------AppLockDao.java(邏輯和黑名單列表類似)/*** 增加程序鎖應(yīng)用*/ public void add(String packageName) {SQLiteDatabase db = mHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("packagename", packageName);db.insert("applock", null, values);db.close(); }/*** 刪除程序鎖應(yīng)用* * @param number*/ public void delete(String packageName) {SQLiteDatabase db = mHelper.getWritableDatabase();db.delete("applock", "packagename=?", new String[] { packageName });db.close(); }/*** 查找程序鎖應(yīng)用* * @param number* @return*/ public boolean find(String packageName) {SQLiteDatabase db = mHelper.getWritableDatabase();Cursor cursor = db.query("applock", null, "packagename=?",new String[] { packageName }, null, null, null);boolean result = false;if (cursor.moveToFirst()) {result = true;}cursor.close();db.close();return result; }/*** 查找已加鎖列表* * @return*/ public ArrayList<String> findAll() {SQLiteDatabase db = mHelper.getWritableDatabase();Cursor cursor = db.query("applock", new String[] { "packagename" },null, null, null, null, null);ArrayList<String> list = new ArrayList<String>();while (cursor.moveToNext()) {String packageName = cursor.getString(0);list.add(packageName);}cursor.close();db.close();return list; }監(jiān)聽(tīng)list item點(diǎn)擊事件,向數(shù)據(jù)庫(kù)添加一些數(shù)據(jù)
lvUnLock.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {AppInfo info = mUnlockList.get(position);mDao.add(info.packageName);} });已加鎖和未加鎖數(shù)據(jù)設(shè)置
private ArrayList<AppInfo> mLockedList;// 已加鎖列表集合 private ArrayList<AppInfo> mUnlockList;// 未加鎖列表集合private Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) {// 設(shè)置未加鎖數(shù)據(jù)mUnlockAdapter = new AppLockAdapter(false);lvUnLock.setAdapter(mUnlockAdapter);// 設(shè)置已加鎖數(shù)據(jù)mLockedAdapter = new AppLockAdapter(true);lvLocked.setAdapter(mLockedAdapter);}; };/*** 初始化應(yīng)用列表數(shù)據(jù)*/ private void initData() {new Thread() {@Overridepublic void run() {mList = AppInfoProvider.getAppInfos(AppLockActivity.this);mLockedList = new ArrayList<AppInfo>();mUnlockList = new ArrayList<AppInfo>();for (AppInfo info : mList) {boolean isLocked = mDao.find(info.packageName);if (isLocked) {mLockedList.add(info);} else {mUnlockList.add(info);}}mHandler.sendEmptyMessage(0);}}.start(); }界面效果完善
點(diǎn)擊鎖子圖標(biāo)后, 實(shí)現(xiàn)加鎖和去加鎖的邏輯, 界面跟著更新class AppLockAdapter extends BaseAdapter {private boolean isLocked;//true表示已加鎖數(shù)據(jù)public AppLockAdapter(boolean isLocked) {this.isLocked = isLocked;}@Overridepublic int getCount() {if (isLocked) {return mLockedList.size();} else {return mUnlockList.size();}}@Overridepublic AppInfo getItem(int position) {if (isLocked) {return mLockedList.get(position);} else {return mUnlockList.get(position);}}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = View.inflate(AppLockActivity.this,R.layout.list_applock_item, null);holder = new ViewHolder();holder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);holder.ivLock = (ImageView) convertView.findViewById(R.id.iv_lock);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}final AppInfo info = getItem(position);holder.ivIcon.setImageDrawable(info.icon);holder.tvName.setText(info.name);if(isLocked) {holder.ivLock.setImageResource(R.drawable.unlock);}else {holder.ivLock.setImageResource(R.drawable.lock);}holder.ivLock.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (isLocked) {mDao.delete(info.packageName);// 從數(shù)據(jù)庫(kù)刪除記錄mLockedList.remove(info);// 從已加鎖集合刪除元素mUnlockList.add(info);// 給未加鎖集合添加元素} else {mDao.add(info.packageName);// 向數(shù)據(jù)庫(kù)添加記錄mLockedList.add(info);// 給已加鎖集合添加元素mUnlockList.remove(info);// 從未加鎖集合刪除元素}// 刷新listviewmLockedAdapter.notifyDataSetChanged();mUnlockAdapter.notifyDataSetChanged();}});return convertView;} }更新已加鎖/未加鎖數(shù)量
/*** 更新已加鎖和未加鎖數(shù)量*/ private void updateAppNum() {tvUnLockNum.setText("未加鎖軟件:" + mUnlockList.size() + "個(gè)");tvLockedNum.setText("已加鎖軟件:" + mLockedList.size() + "個(gè)"); }// 每次刷新listview前都會(huì)調(diào)用getCount方法,可以在這里更新數(shù)量 @Override public int getCount() {updateAppNum();if (isLocked) {return mLockedList.size();} else {return mUnlockList.size();} }動(dòng)畫(huà)實(shí)現(xiàn)
- 解決動(dòng)畫(huà)移動(dòng)問(wèn)題導(dǎo)致的原因,動(dòng)畫(huà)沒(méi)有開(kāi)始播放,界面就刷新了。 動(dòng)畫(huà)播放需要時(shí)間的,動(dòng)畫(huà)沒(méi)有播就變成了新的View對(duì)象。就播了新的View對(duì)象, 讓動(dòng)畫(huà)播放完后,再去更新頁(yè)面;public AppLockAdapter(boolean isLocked) {this.isLocked = isLocked;// 右移mLockAnim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF,0, Animation.RELATIVE_TO_SELF, 0);mLockAnim.setDuration(500);// 左移mUnLockAnim = new TranslateAnimation(Animation.RELATIVE_TO_SELF,0f, Animation.RELATIVE_TO_SELF, -1f,Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,0);mUnLockAnim.setDuration(500); }holder.ivLock.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (isLocked) {view.startAnimation(mUnLockAnim);mUnLockAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}//監(jiān)聽(tīng)動(dòng)畫(huà)結(jié)束事件@Overridepublic void onAnimationEnd(Animation animation) {mDao.delete(info.packageName);// 從數(shù)據(jù)庫(kù)刪除記錄mLockedList.remove(info);// 從已加鎖集合刪除元素mUnlockList.add(info);// 給未加鎖集合添加元素// 刷新listviewmLockedAdapter.notifyDataSetChanged();mUnlockAdapter.notifyDataSetChanged();}});} else {view.startAnimation(mLockAnim);mLockAnim.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}//監(jiān)聽(tīng)動(dòng)畫(huà)結(jié)束事件@Overridepublic void onAnimationEnd(Animation animation) {mDao.add(info.packageName);// 向數(shù)據(jù)庫(kù)添加記錄mLockedList.add(info);// 給已加鎖集合添加元素mUnlockList.remove(info);// 從未加鎖集合刪除元素// 刷新listviewmLockedAdapter.notifyDataSetChanged();mUnlockAdapter.notifyDataSetChanged();}});}} });
總結(jié)
- 上一篇: MySQL update正在执行中突然断
- 下一篇: 高性能 浏览器网络