手机卫士day11

day11

- 系统进程显示和隐藏

    - 创建进程管理设置页面:ProcessManagerSettingActivity
    - 编写设置页面布局文件
    - 监听Checkbox的勾选事件,更新本地SharePreference

            // 根据本地记录,更新checkbox状态
            boolean showSystem = mPrefs.getBoolean("show_system_process", true);
            if (showSystem) {
                cbShowSystem.setChecked(true);
                cbShowSystem.setText("显示系统进程");
            } else {
                cbShowSystem.setChecked(false);
                cbShowSystem.setText("不显示系统进程");
            }

            // 设置状态勾选监听
            cbShowSystem.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    if (isChecked) {
                        cbShowSystem.setText("显示系统进程");
                        mPrefs.edit().putBoolean("show_system_process", true).commit();
                    } else {
                        cbShowSystem.setText("不显示系统进程");
                        mPrefs.edit().putBoolean("show_system_process", false)
                                .commit();
                    }
                }
            });

    - 根据sp记录的是否显示系统进程,更新listview的显示个数

            @Override
            public int getCount() {
                // 通过判断是否显示系统进程,更新list的数量
                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);
            }

            @Override
            protected void onActivityResult(int requestCode, int resultCode, Intent data) {
                // 当从设置页面回跳回来之后,刷新listview
                mAdapter.notifyDataSetChanged();
            }

- 锁屏清理

    - 演示金山进程管理效果
    - 后台启动服务,监听广播

            //判断锁屏清理的广播是否正在运行
            boolean serviceRunning = ServiceStatusUtils.isServiceRunning(
                            "com.itheima.mobilesafeteach.service.AutoKillService", this);

            if (serviceRunning) {
                cbLockClear.setChecked(true);
                cbLockClear.setText("当前状态:锁屏清理已经开启");
            } else {
                cbLockClear.setChecked(false);
                cbLockClear.setText("当前状态:锁屏清理已经关闭");
            }

            cbLockClear.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                @Override
                public void onCheckedChanged(CompoundButton buttonView,
                        boolean isChecked) {
                    Intent intent = new Intent(ProcessManagerSettingActivity.this,
                            AutoKillService.class);
                    if (isChecked) {
                        // 启动锁屏清理的服务
                        startService(intent);
                        cbLockClear.setText("当前状态:锁屏清理已经开启");
                    } else {
                        // 关闭锁屏清理的服务
                        stopService(intent);
                        cbLockClear.setText("当前状态:锁屏清理已经关闭");
                    }
                }
            });

            -------------------------------------

            /**
             * 锁屏清理进程的服务
             * 
             * @author Kevin
             * 
             */
            public class AutoKillService extends Service {

                private InnerScreenOffReceiver mReceiver;

                @Override
                public IBinder onBind(Intent intent) {
                    return null;
                }

                @Override
                public void onCreate() {
                    super.onCreate();
                    //监听屏幕关闭的广播, 注意,该广播只能在代码中注册,不能在清单文件中注册
                    mReceiver = new InnerScreenOffReceiver();
                    IntentFilter filter = new IntentFilter();
                    filter.addAction(Intent.ACTION_SCREEN_OFF);
                    registerReceiver(mReceiver, filter);
                }

                @Override
                public void onDestroy() {
                    super.onDestroy();

                    unregisterReceiver(mReceiver);
                    mReceiver = null;
                }

                /**
                 * 锁屏关闭的广播接收者
                 * 
                 * @author Kevin
                 * 
                 */
                class InnerScreenOffReceiver extends BroadcastReceiver {

                    @Override
                    public void onReceive(Context context, Intent intent) {
                        System.out.println("屏幕关闭...");
                        // 杀死后台所有运行的进程
                        ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
                        List<RunningAppProcessInfo> runningAppProcesses = am
                                .getRunningAppProcesses();

                        for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) {
                            // 跳过手机卫士的服务
                            if (runningAppProcessInfo.processName.equals(ctx.getPackageName())) {
                                return;
                            }

                            am.killBackgroundProcesses(runningAppProcessInfo.processName);
                        }
                    }

                }
            }

- 定时器清理(介绍)

        // 在AutoKillService的onCreate中启动定时器,定时清理任务
        mTimer = new Timer();
        mTimer.schedule(new TimerTask() {

            @Override
            public void run() {
                System.out.println("5秒运行一次!");
            }

        }, 0, 5000);

        @Override
        protected void onDestroy() {
            super.onDestroy();
            mTimer.cancel();
            mTimer = null;
        }
  • 桌面Widget(窗口小部件)

    • widget介绍(Android, 瑞星,早期word)
    • widget谷歌文档查看(API Guide->App Components->App Widget)
    • widget开发流程

      1. 在com.itheima.mobilesafe.receiver目录下创建MyWidget并且继承AppWidgetProvider
      2. 在功能清单文件注册,参照文档
      
          <receiver android:name=".receiver.MyWidget" >
              <intent-filter>
                  <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
              </intent-filter>
      
              <meta-data
                  android:name="android.appwidget.provider"
                  android:resource="@xml/appwidget_info" />
          </receiver>
      
      3. 在res/xml/创建文件example_appwidget_info.xml拷贝文档内容
      
          <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    
          android:minWidth="294dp"    
          android:minHeight="72dp"//能被调整的最小宽高,若大于minWidth minHeight 则忽略    
          android:updatePeriodMillis="86400000"//更新周期,毫秒,最短默认半小时    
          android:previewImage="@drawable/preview"//选择部件时 展示的图像,3.0以上使用,默认是ic_launcher    
          android:initialLayout="@layout/example_appwidget"//布局文件
          android:configure="com.example.android.ExampleAppWidgetConfigure"//添加widget之前,先跳转到配置的activity进行相关参数配置,这个我们暂时用不到       
          android:resizeMode="horizontal|vertical"//widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸
          android:widgetCategory="home_screen|keyguard"//分别在屏幕主页和锁屏状态也能显示(4.2+系统才支持)
          android:initialKeyguardLayout="@layout/example_keyguard"//锁屏状态显示的样式(4.2+系统才支持)
          >
          </appwidget-provider>
      
      4. 精简example_appwidget_info.xml文件,最终结果:
      
          <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" >
      
              <TextView
                  android:id="@+id/textView1"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:background="#f00"
                  android:text="我是widget,哈哈哈"
                  android:textSize="30sp" />
          </LinearLayout>
      
    • 简单演示,高低版本对比

    • 仿照金山widget效果, apktool反编译,抄金山布局文件(业内抄袭成风)

      1. 反编译金山apk
      
          使用apktool,可以查看xml文件内容
          apktool d xxx.apk
      2. 在金山清单文件中查找 APPWIDGET_UPDATE, 找到widget注册的代码
      3. 拷贝金山widget的布局文件process_widget_provider.xml到自己的项目中
      4. 从金山项目中拷贝相关资源文件,解决报错 
      5. 运行,查看效果  
      
    • widget生命周期

      /**
       * 窗口小部件widget
       * 
       * @author Kevin
       * 
       */
      public class MyWidget extends AppWidgetProvider {
      
          /**
           * widget的每次变化都会调用onReceive
           */
          @Override
          public void onReceive(Context context, Intent intent) {
              super.onReceive(context, intent);
              System.out.println("MyWidget: onReceive");
          }
      
          /**
           * 当widget第一次被添加时,调用onEnable
           */
          @Override
          public void onEnabled(Context context) {
              super.onEnabled(context);
              System.out.println("MyWidget: onEnabled");
          }
      
          /**
           * 当widget完全从桌面移除时,调用onDisabled
           */
          @Override
          public void onDisabled(Context context) {
              super.onDisabled(context);
              System.out.println("MyWidget: onDisabled");
          }
      
          /**
           * 新增widget时,或者widget更新时,调用onUpdate
           * 更新时间取决于xml中配置的时间,最短为半小时
           */
          @Override
          public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                  int[] appWidgetIds) {
              super.onUpdate(context, appWidgetManager, appWidgetIds);
              System.out.println("MyWidget: onUpdate");
          }
      
          /**
           * 删除widget时,调onDeleted
           */
          @Override
          public void onDeleted(Context context, int[] appWidgetIds) {
              super.onDeleted(context, appWidgetIds);
              System.out.println("MyWidget: onDeleted");
          }
      
          /**
           * 当widget大小发生变化时,调用此方法
           */
          @Override
          public void onAppWidgetOptionsChanged(Context context,
                  AppWidgetManager appWidgetManager, int appWidgetId,
                  Bundle newOptions) {
              System.out.println("MyWidget: onAppWidgetOptionsChanged");
          }
      
      }
      
    • 定时更新widget

      问题: 我们需要通过widget实时显示当前进程数和可用内存,但widget最短也得半个小时才会更新一次, 如何才能间隔比较短的时间来及时更新?
      
      查看金山日志:
      
      当桌面有金山widget时, 金山会在后台启动service:ProcessService,并定时输出如下日志:
      03-29 08:43:03.070: D/MoSecurity.ProcessService(275): updateWidget
      
      该日志在锁屏状态下也一直输出.
      
      解决办法: 后台启动service,UpdateWidgetService, 并在service中启动定时器来控制widget的更新
      
    • 更新widget方法

      /**
       * 定时更新widget的service
       * 
       * @author Kevin
       * 
       */
      public class UpdateWidgetService extends Service {
      
          private Timer mTimer;
          private AppWidgetManager mAWM;
      
          @Override
          public IBinder onBind(Intent intent) {
              return null;
          }
      
          @Override
          public void onCreate() {
              super.onCreate();
      
              mAWM = AppWidgetManager.getInstance(this);
      
              // 启动定时器,每个5秒一更新
              mTimer = new Timer();
              mTimer.schedule(new TimerTask() {
      
                  @Override
                  public void run() {
                      System.out.println("更新widget啦!");
                      updateWidget();
                  }
              }, 0, 5000);
          }
      
          /**
           * 更新widget
           */
          private void updateWidget() {
              // 初始化远程的view对象
              RemoteViews views = new RemoteViews(getPackageName(),
                      R.layout.process_widget);
      
              views.setTextViewText(R.id.tv_running_processes, "正在运行的软件:"
                      + ProcessInfoProvider.getRunningProcessNum(this));
              views.setTextViewText(
                      R.id.tv_memory_left,
                      "可用内存:"
                              + Formatter.formatFileSize(this,
                                      ProcessInfoProvider.getAvailMemory(this)));
      
              // 初始化组件
              ComponentName provider = new ComponentName(this, MyWidget.class);
      
              // 更新widget
              mAWM.updateAppWidget(provider, views);
          }
      
          @Override
          public void onDestroy() {
              super.onDestroy();
              mTimer.cancel();
              mTimer = null;
          }
      }
      
      -----------------------------
      
      启动和销毁service的时机
      
      分析widget的声明周期,在onEnabled和onUpdate中启动服务, 在onDisabled中结束服务
      
    • 注意: APK安装在sd卡上,widget在窗口小部件列表里无法显示。 android:installLocation=”preferExternal”, 修改过来后,需要卸载,再去安装widget才生效;

    • 点击事件处理

      // 初始化延迟意图,pending是等待的意思
      Intent intent = new Intent(this, HomeActivity.class);
      PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
              intent, PendingIntent.FLAG_UPDATE_CURRENT);
      
      // 当点击widget布局时,跳转到主页面
      views.setOnClickPendingIntent(R.id.ll_root, pendingIntent);
      
      //当一键清理被点击是,发送广播,清理内存
      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);
      
      ---------------------------  
      
      /**
       * 杀死后台进程的广播接受者
       * 清单文件中配置action="com.itheima.mobilesafeteach.KILL_ALL"
       * 
       * @author Kevin
       * 
       */
      public class KillAllReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              System.out.println("kill all...");
              // 杀死后台所有运行的进程
              ProcessInfoProvider.killAll(context);
          }
      }
      
      ---------------------------
      
       <receiver android:name=".receiver.KillAllReceiver" >
          <intent-filter>
              <action android:name="com.itheima.mobilesafeteach.KILL_ALL" />
          </intent-filter>
       </receiver>
      
    • 做一个有情怀的程序员, 拒绝耗电!

      当锁屏关闭时,停止widget定时器的更新
      
      UpdateWidgetService:
      
      // 注册屏幕开启和关闭的广播接受者
      mReceiver = new InnerScreenReceiver();
      IntentFilter filter = new IntentFilter();
      filter.addAction(Intent.ACTION_SCREEN_OFF);
      filter.addAction(Intent.ACTION_SCREEN_ON);
      registerReceiver(mReceiver, filter);
      
      /**
       * 屏幕关闭和开启的广播接收者
       * 
       * @author Kevin
       * 
       */
      class InnerScreenReceiver extends BroadcastReceiver {
      
          @Override
          public void onReceive(Context context, Intent intent) {
              String action = intent.getAction();
              if (Intent.ACTION_SCREEN_OFF.equals(action)) {// 屏幕关闭
                  if (mTimer != null) {
                      // 停止定时器
                      mTimer.cancel();
                      mTimer = null;
                  }
              } else {// 屏幕开启
                  startTimer();
              }
          }
      }
      
  • 程序锁

    • 高级工具中添加程序锁入口
    • 新建程序锁页面 AppLockActivity
    • 程序锁页面布局文件实现

      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" >
      
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:orientation="horizontal" >
      
              <TextView
                  android: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" />
      
              <TextView
                  android: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>
      
          <LinearLayout
              android:id="@+id/ll_unlock"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
      
              <TextView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="未加锁软件:x个"
                  android:textColor="#000" />
      
              <ListView
                  android:id="@+id/lv_unlock"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
          </LinearLayout>
      
          <LinearLayout
              android:id="@+id/ll_locked"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:visibility="gone" >
      
              <TextView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="已加锁软件:x个"
                  android:textColor="#000" />
      
              <ListView
                  android:id="@+id/lv_locked"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
          </LinearLayout>
      
      </LinearLayout>
      
    • 点击标签切换页面

      @Override
      public void onClick(View v) {
          switch (v.getId()) {
          case R.id.tv_unlock:// 展示未加锁页面,隐藏已加锁页面
              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:// 展示已加锁页面,隐藏未加锁页面
              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;
          }
      }
      
    • 应用列表信息展现(展现全部应用列表数据)

    • 使用数据库保存已加锁的软件

      AppLockOpenHelper.java
      
      // 创建表, 两个字段,_id, packagename(应用包名)
      db.execSQL("create table applock (_id integer primary key autoincrement, packagename varchar(50))");
      
      ----------------------------------
      
      AppLockDao.java(逻辑和黑名单列表类似)
      
      /**
       * 增加程序锁应用
       */
      public void add(String packageName) {
          SQLiteDatabase db = mHelper.getWritableDatabase();
          ContentValues values = new ContentValues();
          values.put("packagename", packageName);
          db.insert("applock", null, values);
          db.close();
      }
      
      /**
       * 删除程序锁应用
       * 
       * @param number
       */
      public void delete(String packageName) {
          SQLiteDatabase db = mHelper.getWritableDatabase();
          db.delete("applock", "packagename=?", new String[] { packageName });
          db.close();
      }
      
      /**
       * 查找程序锁应用
       * 
       * @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;
      }
      
    • 监听list item点击事件,向数据库添加一些数据

      lvUnLock.setOnItemClickListener(new OnItemClickListener() {
      
          @Override
          public void onItemClick(AdapterView<?> parent, View view,
                  int position, long id) {
              AppInfo info = mUnlockList.get(position);
              mDao.add(info.packageName);
          }
      });
      
    • 已加锁和未加锁数据设置

      private ArrayList<AppInfo> mLockedList;// 已加锁列表集合
      private ArrayList<AppInfo> mUnlockList;// 未加锁列表集合
      
      private Handler mHandler = new Handler() {
      
          public void handleMessage(android.os.Message msg) {
              // 设置未加锁数据
              mUnlockAdapter = new AppLockAdapter(false);
              lvUnLock.setAdapter(mUnlockAdapter);
      
              // 设置已加锁数据
              mLockedAdapter = new AppLockAdapter(true);
              lvLocked.setAdapter(mLockedAdapter);
          };
      };
      
      /**
       * 初始化应用列表数据
       */
      private void initData() {
          new Thread() {
              @Override
              public 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();
      }
      
    • 界面效果完善

      点击锁子图标后, 实现加锁和去加锁的逻辑, 界面跟着更新
      
      class AppLockAdapter extends BaseAdapter {
      
          private boolean isLocked;//true表示已加锁数据
      
          public AppLockAdapter(boolean isLocked) {
              this.isLocked = isLocked;
          }
      
          @Override
          public int getCount() {
              if (isLocked) {
                  return mLockedList.size();
              } else {
                  return mUnlockList.size();
              }
          }
      
          @Override
          public AppInfo getItem(int position) {
              if (isLocked) {
                  return mLockedList.get(position);
              } else {
                  return mUnlockList.get(position);
              }
          }
      
          @Override
          public long getItemId(int position) {
              return position;
          }
      
          @Override
          public 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() {
      
                  @Override
                  public void onClick(View v) {
                      if (isLocked) {
                          mDao.delete(info.packageName);// 从数据库删除记录
                          mLockedList.remove(info);// 从已加锁集合删除元素
                          mUnlockList.add(info);// 给未加锁集合添加元素
                      } else {
                          mDao.add(info.packageName);// 向数据库添加记录
                          mLockedList.add(info);// 给已加锁集合添加元素
                          mUnlockList.remove(info);// 从未加锁集合删除元素
                      }
      
                      // 刷新listview
                      mLockedAdapter.notifyDataSetChanged();
                      mUnlockAdapter.notifyDataSetChanged();
                  }
              });
      
              return convertView;
          }
      }
      
    • 更新已加锁/未加锁数量

      /**
       * 更新已加锁和未加锁数量
       */
      private void updateAppNum() {
          tvUnLockNum.setText("未加锁软件:" + mUnlockList.size() + "个");
          tvLockedNum.setText("已加锁软件:" + mLockedList.size() + "个");
      }
      
      // 每次刷新listview前都会调用getCount方法,可以在这里更新数量
      @Override
      public int getCount() {
          updateAppNum();
      
          if (isLocked) {
              return mLockedList.size();
          } else {
              return mUnlockList.size();
          }
      }
      
    • 动画实现

      - 解决动画移动问题
      
      导致的原因,动画没有开始播放,界面就刷新了。
      动画播放需要时间的,动画没有播就变成了新的View对象。就播了新的View对象,
      让动画播放完后,再去更新页面;
      
      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() {
      
          @Override
          public void onClick(View v) {
              if (isLocked) {
                  view.startAnimation(mUnLockAnim);
                  mUnLockAnim
                          .setAnimationListener(new AnimationListener() {
      
                              @Override
                              public void onAnimationStart(
                                      Animation animation) {
                              }
      
                              @Override
                              public void onAnimationRepeat(
                                      Animation animation) {
                              }
                              //监听动画结束事件
                              @Override
                              public void onAnimationEnd(
                                      Animation animation) {
                                  mDao.delete(info.packageName);// 从数据库删除记录
                                  mLockedList.remove(info);// 从已加锁集合删除元素
                                  mUnlockList.add(info);// 给未加锁集合添加元素
      
                                  // 刷新listview
                                  mLockedAdapter.notifyDataSetChanged();
                                  mUnlockAdapter.notifyDataSetChanged();
                              }
                          });
              } else {
                  view.startAnimation(mLockAnim);
                  mLockAnim.setAnimationListener(new AnimationListener() {
      
                      @Override
                      public void onAnimationStart(Animation animation) {
                      }
      
                      @Override
                      public void onAnimationRepeat(Animation animation) {
                      }
      
                      //监听动画结束事件
                      @Override
                      public void onAnimationEnd(Animation animation) {
                          mDao.add(info.packageName);// 向数据库添加记录
                          mLockedList.add(info);// 给已加锁集合添加元素
                          mUnlockList.remove(info);// 从未加锁集合删除元素
                          // 刷新listview
                          mLockedAdapter.notifyDataSetChanged();
                          mUnlockAdapter.notifyDataSetChanged();
                      }
                  });
              }
          }
      });
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值