A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 小鲁哥哥 于 2017-4-12 14:33 编辑


Android课程同步笔记day12:Android应用之安全卫士
程序锁
程序锁可以将某一个应用上锁,当进入该程序时需要输入手机防盗密码,UI界面如图所示

在程序锁界面中使用Fragment 控件分别展示未加锁应用和已加锁应用,将一个应用加锁后,此时会将该应用存入到数据库中。当在常用工具界面中打开程序锁服务时,运行在后台的服务监测当前打开的应用,如果打开的应用在数据库中,就说明程序是加锁程序,会弹出输入密码界面,密码输入正确后才能打开应用(密码为手机防盗密码)。

看门狗
看门狗服务顾名思义就是替用户监测手机中的一些信息,这里的看门狗主要是为上面的程序锁功能服务的,它可以在用户点击加锁应用时进入一个输入密码的界面,只有输入密码正确才会进入当前应用中,效果图如图所示:

密码设置和输入界面
上诉功能中只要我们选择某一个应用添加到加锁界面后,并且我们打开了看门狗服务,那么当点击这个应用时就应该输入密码;这里设置密码和输入密码的界面如下图所示;并且在设置密码之前还有一个设置向导的界面


程序锁密码页面结构

根据我们的页面结构图分析来看,首先进入程序锁界面应该判断是否是需要输入密码还是设置密码:
[Java] 纯文本查看 复制代码
public class AppLockSettingActivity extends FragmentActivity {
        private static final String TAG = "AppLockSettingActivity";
        private TextView mTvTitle;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_app_lock_setting);

                mTvTitle = (TextView) findViewById(R.id.als_tv_title);
                // 要么显示密码输入,要么显示密码设置
                // 有密码--》密码输入
                // 没有密码--》密码设置

                String pwd = PreferenceUtils.getString(this, Config.KEY_APP_LOCK_PWD);
                if (TextUtils.isEmpty(pwd)) {
                        // 密码设置
                        loadPwdManagerFragment();
                } else {
                        // 密码输入
                        loadPwEnterFragment();
                }
        }

        /**
         * 进入密码设置界面
         */
        private void loadPwdManagerFragment() {
                Log.d(TAG, "进入密码设置");
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction transaction = fm.beginTransaction();

                transaction.replace(R.id.als_container, new PwdManagerFragment());
                transaction.commit();
        }

        /**
         * 进入密码输入界面
         */
        private void loadPwEnterFragment() {
                Log.d(TAG, "进入密码输入");
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction transaction = fm.beginTransaction();

                transaction.replace(R.id.als_container, new PwdEnterFragment());
                transaction.commit();
        }

        public void setAppLockTitle(String title) {
                mTvTitle.setText(title);
        }
}

创建所有的fragment创建上诉对应的两个fragment以及之前逻辑图中分析所需要用到的fragment,注意需要用supportV4包中的兼容包,兼容低版本。 1.PwdManagerFragmentfragment其实是用来管理需要显示的三个fragment,所以只是作为一个容器来使用和管理;布局文件为
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pwd_manager_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

代码实现
[Java] 纯文本查看 复制代码
public class PwdManagerFragment extends Fragment {
        private static final String TAG = "PwdManagerFragment";

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                Log.d(TAG, "onCreateView");
                View view = inflater.inflate(R.layout.fragment_pwd_manager, container,
                                false);
                
                // 管理显示Fragment
                // 默认显示PwdSetupFragment
                loadPwdSetupFragment();
                return view;
        }
        
        //当activity创建的时候回调
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
                Log.d(TAG, "onActivityCreated");
                // 设置回退栈的监听
                doBackStackListener();

                // 管理显示Fragment
                // 默认显示PwdSetupFragment设置向导界面
                loadPwdSetupFragment();
        }

        private void doBackStackListener() {
                final FragmentManager fm = getChildFragmentManager();
                fm.addOnBackStackChangedListener(new OnBackStackChangedListener() {
                        @Override
                        public void onBackStackChanged() {
                                // 当回退栈发生改变时
                                // 获得栈顶部的fragment
                                int count = fm.getBackStackEntryCount();
                                Log.d(TAG, "回退栈发生改变 count:"+count);
                                if (count > 0) {
                                        BackStackEntry entry = fm.getBackStackEntryAt(count - 1);
                                        String name = entry.getName();
                                        if ("setup".equals(name)) {
                                                setApplockTitle("密码设置向导");
                                        } else if ("setting".equals(name)) {
                                                setApplockTitle("密码设置");
                                        } else if ("confirm".equals(name)) {
                                                setApplockTitle("密码确认");
                                        }
                                }
                        }
                });
        }

        /**设置activity的title*/
        public void setApplockTitle(String title) {
                AppLockSettingActivity activity = (AppLockSettingActivity) getActivity();
                activity.setAppLockTitle(title);
        }

        /**显示设置向导界面*/
        public void loadPwdSetupFragment() {
                FragmentManager fm = getChildFragmentManager();
                // 开启事务
                FragmentTransaction transaction = fm.beginTransaction();

                // 设置动画
                transaction.setCustomAnimations(0, R.anim.f_exit, R.anim.f_pop_enter,R.anim.f_pop_exit);

                // 设置fragment
                transaction.replace(R.id.pwd_manager_container, new PwdSetupFragment());

                // 添加到回退栈
                transaction.addToBackStack("setup");

                // 提交事务
                transaction.commit();
        }

        /**显示设置密码界面*/
        public void loadPwdSettingFragment() {
                FragmentManager fm = getChildFragmentManager();
                FragmentTransaction transaction = fm.beginTransaction();
                // 设置动画
                transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit,
                                R.anim.f_pop_enter, R.anim.f_pop_exit);
                transaction.replace(R.id.pwd_manager_container,
                                new PwdSettingFragment());
                // 添加到回退栈
                transaction.addToBackStack("setting");
                transaction.commit();
        }

        /**显示确认密码界面*/
        public void loadPwdConfirmFragment(String password) {
                FragmentManager fm = getChildFragmentManager();
                FragmentTransaction transaction = fm.beginTransaction();
                // 设置动画
                transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit,
                                R.anim.f_pop_enter, R.anim.f_pop_exit);

                PwdConfirmFragment fragment = new PwdConfirmFragment();
                Bundle args = new Bundle();
                args.putString("password", password);
                fragment.setArguments(args);

                transaction.replace(R.id.pwd_manager_container, fragment);
                // 添加到回退栈
                transaction.addToBackStack("confirm");
                transaction.commit();
        }

        public void popBack() {
                FragmentManager fm = getChildFragmentManager();
                fm.popBackStack();
        }
}

注意:
transaction.setCustomAnimations(R.anim.f_enter, R.anim.f_exit, R.anim.f_pop_enter, R.anim.f_pop_exit);
代表的是设置每一个fragment切换时的动画,前面两个参数分别代表的是当前展示的fragment从右边进来的时候动画以及出去的动画;而最后两个参数代表的是当前fragment如果存在于back stack回退栈中左边进来的时候以及出去的时候的动画。
回退栈的作用就是可以让activity中的所有fragment可以实现点击返回键的时候直接返回到上一个fragment,不过前提是打开的这个fragment必须通过transcation添加到回退栈。
f_enter.xml:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="100%p"
    android:toXDelta="0" >
</translate>
f_exit.xml:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="0"
    android:toXDelta="-100%p" >
</translate>
f_pop_enter.xml:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="-100%p"
    android:toXDelta="0" >
</translate>
f_pop_exit.xml:
[XML] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="0"
    android:toXDelta="100%p" >
</translate>
密码设置向导fragment
该界面主要是给用户展示如何设置密码,那么需要用到两个api;第一个是设置当前的mPatternView不可以让用户点击;第二个设置一个演示的密码:mPatternView.setPattern(DisplayMode.Animate,"0368");
界面布局:
[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:background="@android:color/black"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:text="按照以下手势进行密码设置"
        android:textColor="#ffffff" />

    <com.itheima.zphuanlove.view.LockPatternView
        android:id="@+id/fragment_pattern_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:layout_weight="100" />

    <Button
        android:id="@+id/fragment_btn_next"
        style="@style/btnCancelNormal"
        android:layout_width="match_parent"
        android:layout_margin="8dp"
        android:layout_weight="1"
        android:text="下一步" /></LinearLayout>[/align][align=left]
完整的代码如下:
[Java] 纯文本查看 复制代码
public class PwdSetupFragment extends Fragment implements OnClickListener {
        private static final String TAG = "PwdSetupFragment";
        private Button mBtnNext;
        private LockPatternView mPatternView;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_pwd_setup, container,
                                false);
                initView(view);

                // 设置点击事件
                initEvent();

                return view;
        }

        private void initView(View view) {
                mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);
                mPatternView = (LockPatternView) view
                                .findViewById(R.id.fragment_pattern_view);

                // 设置图案view不可使用,要显示动画
                mPatternView.disableInput();
                mPatternView.setPattern(DisplayMode.Animate, "0368");
        }

        private void initEvent() {
                mBtnNext.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
                if (v == mBtnNext) {
                        clickNext();
                }
        }

        private void clickNext() {
                // 切换到密码设置的fragment中
                PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
                fragment.loadPwdSettingFragment();
        }
        
        @Override
        public void onDestroy() {
                super.onDestroy();
                Log.d(TAG, "manager fragment destroy");
        }
}
密码设置fragment
该界面主要是让用户自己输入密码,需要监听用户输入的图案,然后转换成string字符串,通过PwdManagerFragment打开下一个密码确认fragment时传递过去。
界面布局:
[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:background="@android:color/black"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:text="请设置密码"
        android:textColor="#ffffff" />

    <com.itheima.zphuanlove.view.LockPatternView
        android:id="@+id/fragment_pattern_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:layout_weight="100" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/fragment_btn_pre"
            style="@style/btnCancelNormal"
            android:layout_width="match_parent"
            android:layout_marginRight="4dp"
            android:layout_weight="1"
            android:text="上一步" />

        <Button
            android:id="@+id/fragment_btn_next"
            style="@style/btnCancelNormal"
            android:layout_width="match_parent"
            android:layout_marginLeft="4dp"
            android:layout_weight="1"
            android:text="下一步" />
    </LinearLayout>

</LinearLayout>
完整代码:
[Java] 纯文本查看 复制代码
public class PwdSettingFragment extends Fragment implements OnClickListener {
        private Button mBtnPre;
        private Button mBtnNext;
        private LockPatternView mPatternView;

        private String mPassword;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_pwd_setting, container,
                                false);

                initView(view);

                // 设置点击事件
                initEvent();

                return view;
        }

        private void initView(View view) {
                mBtnPre = (Button) view.findViewById(R.id.fragment_btn_pre);
                mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);

                mPatternView = (LockPatternView) view
                                .findViewById(R.id.fragment_pattern_view);
        }

        private void initEvent() {
                mBtnPre.setOnClickListener(this);
                mBtnNext.setOnClickListener(this);

                mPatternView.setOnPatternListener(new OnPatternListener() {
                        @Override
                        public void onPatternStart() {
                        }
                        @Override
                        public void onPatternDetected(List<Cell> pattern) {
                                StringBuilder builder = new StringBuilder();
                                for (int i = 0; i < pattern.size(); i++) {
                                        Cell cell = pattern.get(i);

                                        int p = cell.getRow() * 3 + cell.getColumn();
                                        builder.append(p);
                                }
                                mPassword = builder.toString();
                        }
                        @Override
                        public void onPatternCleared() {
                                mPassword = null;
                        }
                        @Override
                        public void onPatternCellAdded(List<Cell> pattern) {
                        }
                });
        }

        @Override
        public void onClick(View v) {
                if (v == mBtnNext) {
                        clickNext();
                } else if (v == mBtnPre) {
                        clickPre();
                }
        }

        private void clickPre() {
                // // 切换到密码设置向导的fragment中
                // PwdManagerFragment fragment = (PwdManagerFragment)
                // getParentFragment();
                // fragment.loadPwdSetupFragment();

                // 回退操作
                PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
                fragment.popBack();
        }

        private void clickNext() {
                if (TextUtils.isEmpty(mPassword)) {
                        Toast.makeText(getActivity(), "必须去设置密码", Toast.LENGTH_SHORT).show();
                        return;
                }
                // 切换到密码确认的fragment中
                PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
                fragment.loadPwdConfirmFragment(mPassword);
        }
}
重复密码确认fragment
该界面主要点在于获取到设置密码传递过来的密码数据;然后监听当前用户输入的重复密码,在点击设置完成按钮的时候进行比对。
布局文件:

[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:background="@android:color/black"
    android:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="4dp"
        android:text="请确认密码"
        android:textColor="#ffffff" />

    < com.itheima.zphuanlove.view.LockPatternView
        android:id="@+id/fragment_pattern_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:layout_weight="100" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/fragment_btn_pre"
            style="@style/btnCancelNormal"
            android:layout_width="match_parent"
            android:layout_marginRight="4dp"
            android:layout_weight="1"
            android:text="上一步" />

        <Button
            android:id="@+id/fragment_btn_next"
            style="@style/btnCancelNormal"
            android:layout_width="match_parent"
            android:layout_marginLeft="4dp"
            android:layout_weight="1"
            android:text="设置完成" />
    </LinearLayout>

</LinearLayout>

完整代码:
[Java] 纯文本查看 复制代码
public class PwdConfirmFragment extends Fragment implements OnClickListener{
        private Button mBtnPre;
        private Button mBtnNext;

        private LockPatternView mPatternView;

        private String mConfirmPassword;
        private String mPassword;

        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);

                Bundle arguments = getArguments();
                mPassword = arguments.getString("password");
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_pwd_confirm, container,
                                false);

                initView(view);

                // 设置点击事件
                initEvent();

                return view;
        }

        private void initView(View view) {
                mBtnPre = (Button) view.findViewById(R.id.fragment_btn_pre);
                mBtnNext = (Button) view.findViewById(R.id.fragment_btn_next);

                mPatternView = (LockPatternView) view
                                .findViewById(R.id.fragment_pattern_view);
        }

        private void initEvent() {
                mBtnPre.setOnClickListener(this);
                mBtnNext.setOnClickListener(this);

                mPatternView.setOnPatternListener(new OnPatternListener() {

                        @Override
                        public void onPatternStart() {
                        }

                        @Override
                        public void onPatternDetected(List<Cell> pattern) {

                                // 密码获得
                                // 记录密码
                                StringBuilder builder = new StringBuilder();
                                for (int i = 0; i < pattern.size(); i++) {
                                        Cell cell = pattern.get(i);

                                        int p = cell.getRow() * 3 + cell.getColumn();
                                        builder.append(p);
                                }

                                mConfirmPassword = builder.toString();

                        }

                        @Override
                        public void onPatternCleared() {
                                mConfirmPassword = null;
                        }

                        @Override
                        public void onPatternCellAdded(List<Cell> pattern) {
                        }
                });
        }

        @Override
        public void onClick(View v) {
                if (v == mBtnNext) {
                        clickNext();
                } else if (v == mBtnPre) {
                        clickPre();
                }
        }

        private void clickPre() {
                // 切换到密码设置的fragment中
                // PwdManagerFragment fragment = (PwdManagerFragment)
                // getParentFragment();
                // fragment.loadPwdSettingFragment();

                PwdManagerFragment fragment = (PwdManagerFragment) getParentFragment();
                fragment.popBack();
        }

        private void clickNext() {
                if (TextUtils.isEmpty(mConfirmPassword)) {
                        Toast.makeText(getActivity(), "必须去设置确认密码", Toast.LENGTH_SHORT)
                                        .show();
                        return;
                }

                if (!mConfirmPassword.equals(mPassword)) {
                        Toast.makeText(getActivity(), "两次密码不一致", Toast.LENGTH_SHORT).show();
                        return;
                }

                // 密码设置完成,进行其他跳转
                // Toast.makeText(getActivity(), "密码设置完成,进行其他跳转", Toast.LENGTH_SHORT)
                // .show();
                //

                // 存储密码
                PreferenceUtils.setString(getActivity(), Config.KEY_APP_LOCK_PWD,
                                mPassword);

                Intent intent = new Intent(getActivity(), AppLockActivity.class);
                getActivity().startActivity(intent);

                getActivity().finish();
        }
}

密码输入界面fragment
当前面的设置密码一系列逻辑实现后,当我们从常用工具点击密码锁再次进来的 时候就应该弹出设置密码的fragment。主要核心点就是判断输入的密码与我们保存在sp中的密码是否一致来进行比对。
布局文件:

[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:background="@android:color/black"
    android:orientation="vertical" >

    <com.itheima.zphuanlove.view.LockPatternView
        android:id="@+id/fragment_pattern_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:layout_weight="100" />

</LinearLayout>

完整代码:
[Java] 纯文本查看 复制代码
public class PwdEnterFragment extends Fragment {
        private LockPatternView mPatternView;

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                        Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_pwd_enter, container,
                                false);

                initView(view);
                initEvent();
                return view;
        }

        private void initView(View view) {
                mPatternView = (LockPatternView) view
                                .findViewById(R.id.fragment_pattern_view);

                // 设置title显示
                AppLockSettingActivity activity = (AppLockSettingActivity) getActivity();
                activity.setAppLockTitle("密码输入");
        }

        private void initEvent() {
                mPatternView.setOnPatternListener(new OnPatternListener() {
                        @Override
                        public void onPatternStart() {
                        }

                        @Override
                        public void onPatternDetected(List<Cell> pattern) {
                                StringBuilder builder = new StringBuilder();
                                for (int i = 0; i < pattern.size(); i++) {
                                        Cell cell = pattern.get(i);

                                        int p = cell.getRow() * 3 + cell.getColumn();
                                        builder.append(p);
                                }
                                String password = builder.toString();

                                // 比对密码
                                String pwd = PreferenceUtils.getString(getActivity(),
                                                Config.KEY_APP_LOCK_PWD);

                                if (!pwd.equals(password)) {
                                        // 不同
                                        mPatternView.setDisplayMode(DisplayMode.Wrong);
                                        return;
                                }

                                // 正确,页面跳转
                                Intent intent = new Intent(getActivity(), AppLockActivity.class);
                                getActivity().startActivity(intent);

                                getActivity().finish();
                        }

                        @Override
                        public void onPatternCleared() {
                        }

                        @Override
                        public void onPatternCellAdded(List<Cell> pattern) {
                        }
                });
        }
}

程序锁activity展示界面UI展示界面:

代码如下:
[Java] 纯文本查看 复制代码
public class SegmentView extends LinearLayout implements View.OnClickListener {
        private TextView mTvLeft;
        private TextView mTvRight;

        private OnCheckListener mListener;

        private boolean mLeftSelected;

        public SegmentView(Context context) {
                this(context, null);
        }

        public SegmentView(Context context, AttributeSet attrs) {
                super(context, attrs);

                // /挂载xml
                View.inflate(context, R.layout.view_segment, this);

                mTvLeft = (TextView) findViewById(R.id.segment_tv_left);
                mTvRight = (TextView) findViewById(R.id.segment_tv_right);

                // 设置默认选中
                mTvLeft.setSelected(true);
                mTvRight.setSelected(false);
                mLeftSelected = true;

                // 初始化事件
                initEvent();
        }

        private void initEvent() {
                mTvLeft.setOnClickListener(this);
                mTvRight.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
                if (v == mTvLeft) {
                        // 如果左侧没有被选中 ,才能被选中
                        if (mLeftSelected) {
                                return;
                        }

                        // 点击左侧,让左侧选中
                        mTvLeft.setSelected(true);
                        mTvRight.setSelected(false);
                        mLeftSelected = true;

                        // 改变activity UI显示 ---》 控件的存在依赖于activity业务逻辑

                        // 接口回调
                        if (mListener != null) {
                                mListener.onChecked(mTvLeft, true);
                        }

                } else if (v == mTvRight) {
                        // 如果右侧没有被选中 ,才能被选中
                        if (!mLeftSelected) {
                                return;
                        }

                        // 点击右侧,让右侧选中
                        mTvLeft.setSelected(false);
                        mTvRight.setSelected(true);
                        mLeftSelected = false;

                        // 改变activity UI显示
                        // 接口回调
                        if (mListener != null) {
                                mListener.onChecked(mTvRight, false);
                        }
                }
        }

        /**
         * 设置监听器
         * 
         * @param listener
         */
        public void setOnCheckListener(OnCheckListener listener) {
                this.mListener = listener;
        }

        public interface OnCheckListener {

                /**
                 * 当选中时
                 * 
                 * @param v
                 *            :选中的view
                 * @param leftSelected
                 *            :是否左侧选中
                 */
                void onChecked(View v, boolean leftSelected);
        }
}

主要涉及到一个接口回调的实现,目的是当点击对应的加锁和未加锁时需要让activity界面下方显示对应的界面。
程序锁下方对应的界面为listview,这里直接用两个listview来交替实现,当然有兴趣的同学也可以通过fragment去实现。

AppLockActivity的布局为:
[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" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@color/title_bg" >

        < com.itheima.zphuanlove.view.SegmentView
            android:id="@+id/al_segmentview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />
    </RelativeLayout>

    <TextView
        android:id="@+id/al_tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#55000000"
        android:padding="4dp"
        android:text="未加锁"
        android:textColor="#ffffff" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ListView
            android:id="@+id/al_listview_lock"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone" >
        </ListView>

        <ListView
            android:id="@+id/al_listview_unlock"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        </ListView>
    </RelativeLayout>

</LinearLayout>
初始化控件并先将分段控件的点击事件给先实现好:
[Java] 纯文本查看 复制代码
public class AppLockActivity extends Activity {
        private SegmentView mSegmentView;
        private ListView mLockListView;
        private ListView mUnLockListView;
        private TextView mTvTitle;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_app_lock);

                initView();
                initEvent();
        }

        private void initView() {
                mSegmentView = (SegmentView) findViewById(R.id.al_segmentview);
                mLockListView = (ListView) findViewById(R.id.al_listview_lock);
                mUnLockListView = (ListView) findViewById(R.id.al_listview_unlock);
                mTvTitle = (TextView) findViewById(R.id.al_tv_title);
        }

        private void initEvent() {
                // 分段控件左右选中时,会影响下面布局的显示
                mSegmentView.setOnCheckListener(new OnCheckListener() {
                        @Override
                        public void onChecked(View v, boolean leftSelected) {
                                Toast.makeText(AppLockActivity.this,
                                                leftSelected ? "左侧选中" : "右侧选中", Toast.LENGTH_SHORT)
                                                .show();
                                if (leftSelected) {
                                        // 显示未加锁的
                                        mLockListView.setVisibility(View.GONE);
                                        mUnLockListView.setVisibility(View.VISIBLE);
                                } else {
                                        // 显示已经加锁的
                                        mLockListView.setVisibility(View.VISIBLE);
                                        mUnLockListView.setVisibility(View.GONE);
                                }
                        }
                });
        }
}
程序锁页面Adpater实现
接下来就需要通过adpater将数据展示出来进行展示,由于这里有两个listview,所以一个adapter需要进行一些判断才可以实现是加锁还是未加锁的,然后分别传入不同的数据来进行不同的界面展示。
这里首先可以通过制造假数据的形式来先测试界面
[Java] 纯文本查看 复制代码
private void initData() {

                // 加载list数据 --假数据展示
                mLockDatas = new ArrayList<AppInfo>();
                for (int i = 0; i < 30; i++) {

                        AppInfo bean = new AppInfo();
                        bean.name = "加锁的程序-" + i;

                        mLockDatas.add(bean);
                }

                mUnlockDatas = new ArrayList<AppInfo>();
                for (int i = 0; i < 30; i++) {

                        AppInfo bean = new AppInfo();
                        bean.name = "未加锁的程序-" + i;

                        mUnlockDatas.add(bean);
                }

                // 给未加锁的设置adapter
                mUnlockAdapter = new ApplockAdapter(false);
                mUnLockListView.setAdapter(mUnlockAdapter);
                // 给已加锁的设置adapter
                mLockAdapter = new ApplockAdapter(true);
                mLockListView.setAdapter(mLockAdapter);
        }

        private class ApplockAdapter extends BaseAdapter {
                private boolean mLocked;

                public ApplockAdapter(boolean locked) {
                        this.mLocked = locked;
                }

                @Override
                public int getCount() {
                        if (mLocked) {
                                // 已经上锁的
                                if (mLockDatas != null) {
                                        mTvTitle.setText("加锁程序(" + mLockDatas.size() + ")");
                                        return mLockDatas.size();
                                }
                                mTvTitle.setText("加锁程序(0)");
                        } else {
                                // 未上锁的
                                if (mUnlockDatas != null) {
                                        mTvTitle.setText("未加锁程序(" + mUnlockDatas.size() + ")");
                                        return mUnlockDatas.size();
                                }
                                mTvTitle.setText("未加锁程序(0)");
                        }
                        return 0;
                }

                @Override
                public Object getItem(int position) {
                        if (mLocked) {
                                // 已经上锁的
                                if (mLockDatas != null) {
                                        return mLockDatas.get(position);
                                }
                        } else {
                                // 未上锁的
                                if (mUnlockDatas != null) {
                                        return mUnlockDatas.get(position);
                                }
                        }
                        return null;
                }

                @Override
                public long getItemId(int position) {
                        return position;
                }

                @Override
                public View getView(int position, View convertView, ViewGroup parent) {
                        ViewHolder holder = null;
                        if (convertView == null) {
                                // 没有复用
                                convertView = View.inflate(AppLockActivity.this,
                                                R.layout.item_app_lock, null);
                                holder = new ViewHolder();
                                convertView.setTag(holder);
                                holder.ivIcon = (ImageView) convertView
                                                .findViewById(R.id.item_al_iv_icon);
                                holder.ivLock = (ImageView) convertView
                                                .findViewById(R.id.item_al_iv_lock);
                                holder.tvName = (TextView) convertView
                                                .findViewById(R.id.item_al_tv_name);
                        } else {
                                // 有复用
                                holder = (ViewHolder) convertView.getTag();
                        }

                        // 设置数据
                        AppInfo bean = null;
                        if (mLocked) {
                                bean = mLockDatas.get(position);
                        } else {
                                bean = mUnlockDatas.get(position);
                        }

                        if (bean.icon == null) {
                                holder.ivIcon.setImageResource(R.drawable.ic_default);
                        } else {
                                holder.ivIcon.setImageDrawable(bean.icon);
                        }
                        holder.tvName.setText(bean.name);

                        return convertView;
                }
        }

        private static class ViewHolder {
                ImageView ivIcon;
                TextView tvName;
                ImageView ivLock;
        }
这里的javabean可以直接复用之前在软件管家和进程管理里面使用过的javabean。

数据库的创建
为了记录加锁的应用程序,这里使用数据库的方式来存储;首先创建数据库:
[Java] 纯文本查看 复制代码
public class AppLockDBHelper extends SQLiteOpenHelper {

        public AppLockDBHelper(Context context) {
                super(context, AppLockDB.NAME, null, AppLockDB.VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
                // 新建表
                db.execSQL(AppLockDB.TableApplock.SQL_CREATE_TABLE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        }
}
public interface AppLockDB {
        String NAME = "applock.db";
        int VERSION = 1;

        public interface TableApplock {
                String TABLE_NAME = "t_applock";

                String COLUMN_ID = "_id";
                String COLUMN_PKG = "pkg";// 用来记录上锁的应用的包名

                String SQL_CREATE_TABLE = "create table " + TABLE_NAME + "("
                                + COLUMN_ID + " integer primary key autoincrement,"
                                + COLUMN_PKG + " text unique" + ")";
        }
}
创建一个名为:applock.db的数据库,里面有一张t_applock的表,两个字段一个id一个pkg。

数据库dao的实现
实现数据库的增删改查
[Java] 纯文本查看 复制代码
public class AppLockDao {
        private AppLockDBHelper mHelper;

        public AppLockDao(Context context) {
                mHelper = new AppLockDBHelper(context);
        }

        /**
         * 添加数据
         * 
         * @param packageName
         * @return
         */
        public boolean add(String packageName) {
                SQLiteDatabase db = mHelper.getWritableDatabase();

                ContentValues values = new ContentValues();
                values.put(AppLockDB.TableApplock.COLUMN_PKG, packageName);

                long insert = db
                                .insert(AppLockDB.TableApplock.TABLE_NAME, null, values);

                db.close();

                return insert != -1;
        }

        /**
         * 删除
         * 
         * @param packageName
         * @return
         */
        public boolean delete(String packageName) {
                SQLiteDatabase db = mHelper.getWritableDatabase();

                String whereClause = AppLockDB.TableApplock.COLUMN_PKG + "=?";
                String[] whereArgs = new String[] { packageName };
                int delete = db.delete(AppLockDB.TableApplock.TABLE_NAME, whereClause,
                                whereArgs);

                db.close();

                return delete > 0;
        }

        /**
         * 查询是否上锁
         * 
         * @param packageName
         * @return
         */
        public boolean findLock(String packageName) {
                SQLiteDatabase db = mHelper.getReadableDatabase();
                String sql = "select count(_id) from "
                                + AppLockDB.TableApplock.TABLE_NAME + " where "
                                + AppLockDB.TableApplock.COLUMN_PKG + "=?";
                Cursor cursor = db.rawQuery(sql, new String[] { packageName });

                int count = 0;
                if (cursor != null) {
                        if (cursor.moveToNext()) {
                                count = cursor.getInt(0);
                        }

                        cursor.close();
                }
                db.close();

                return count != 0;
        }
}
创建测试类进行测试
[Java] 纯文本查看 复制代码
public class TestAppLock extends AndroidTestCase {
        public void testAdd() {

                AppLockDao dao = new AppLockDao(getContext());

                boolean add = dao.add("com.abc");

                assertEquals(true, add);
        }

        public void testDelete() {

                AppLockDao dao = new AppLockDao(getContext());

                boolean delete = dao.delete("com.abc");

                assertEquals(true, delete);
        }

        public void testFind() {
                AppLockDao dao = new AppLockDao(getContext());

                boolean find = dao.findLock("com.abc");

                assertEquals(true, find);
        }
}



1 个回复

倒序浏览
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马