Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android---程序鎖(1)展示頁面的搭建

Android---程序鎖(1)展示頁面的搭建

編輯:關於Android編程

一.寫在前面的話

在日常使用手機的過程中,我們經常希望有這樣一個功能:可以對我們的某一個應用加鎖,進入的時候需要輸入密碼驗證身份,然後才可以進入主界面,這就是一個程序鎖的功能。其實這種功能並不難實現,正好在我最近跟著黑馬74期視頻敲的一個大的Demo裡有這一塊的內容,所以決定記錄一下實現的方式。純記錄。。

二.界面顯示邏輯

2.1界面效果圖
這裡寫圖片描述
這裡寫圖片描述

2.2layout布局文件
這裡我們將“未加鎖”和“已加鎖”兩個模塊的ListView寫在同一個布局文件中,用android:visibility=”“ 屬性結合上方按鈕的選中來決定下方是顯示哪一個ListView
布局文件代碼如下:




    

注意到@+id/ll_lock android:visibility=”gone”,也就是通過對這兩個屬性的改變來控制下方的ListView到底顯示的是哪一個。

2.3ListView的數據來源
有了ListView我們自然就會想到,LIstView始終需要兩個部分,數據源和數據適配器,也就是Adapter。首先我記錄一下展示數據的來源。

 //區分已加鎖應用和未加鎖的應用
    private void initData() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                //1.獲取手機中所有的應用
                mAppInfoList = appInfoProvider.getAppInfoList(getApplicationContext());
                //2.區分已加鎖應用和未加鎖應用
                mLockList = new ArrayList();
                mUnlockList = new ArrayList();
                //3.獲取數據庫中已加鎖應用包名的集合
                mDao = appLockDao.getInstance(getApplicationContext());
                List lockPackageList = mDao.findAll();
                for (AppInfo appInfo : mAppInfoList) {
                    //4.如果循環到的應用的包名在數據庫中,說明是已經加鎖了的應用
                    if (lockPackageList.contains(appInfo.getPackageName())) {
                        mLockList.add(appInfo);
                    } else {
                        mUnlockList.add(appInfo);
                    }

                }
                //5.告知主線程,數據准備好了,可以使用了 消息機制
                mHandler.sendEmptyMessage(0);
            }
        }).start();


    }

其中:appInfoProvider.getAppInfoList(getApplicationContext());
mDao = appLockDao.getInstance(getApplicationContext());
List lockPackageList = mDao.findAll();
這三個是我已經封裝好的方法,分別用於拿到手機中所有的應用;拿到歲數據庫增刪改查的對象;拿到目前數據庫中已經有的數據。
這個意思就是說,我將已經加鎖的應用放到數據庫中,然後將已經加鎖和未加鎖的應用分別放到兩個集合中:mLockList,mUnlockList。由於拿數據這個操作可能耗時,所以我們將這個方法放到線程中去執行。最後在利用消息機制通知主線程,數據已准備好。

2.4Adapter的設置

由於我們將兩個ListVIew都寫在同一個布局裡,所以我們也用一個Adapter同時去配置兩個LIstView,只是加上一個private boolean isLock; 這個標記,來區分當前是配置哪一個ListView。

class myAdapter extends BaseAdapter {
        private boolean isLock;

        //用於區分已加鎖和未加鎖應用的標識   重寫的構造方法
        public myAdapter(boolean isLock) {
            this.isLock = isLock;
        }

        @Override
        public int getCount() {
            if (isLock) {
                tv_lock.setText("已加鎖應用:" + mLockList.size());
                return mLockList.size();
            } else {
                tv_unlock.setText("未加鎖應用:" + mUnlockList.size());
                return mUnlockList.size();
            }
        }

        @Override
        public AppInfo getItem(int position) {
            if (isLock) {
                return mLockList.get(position);
            } else {
                return mUnlockList.get(position);
            }
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = View.inflate(getApplicationContext(), R.layout.listview_islock_item, null);
                holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
                holder.iv_lock = (ImageView) convertView.findViewById(R.id.iv_lock);
                holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);

                convertView.setTag(holder);

            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            final AppInfo appinfo = getItem(position);
            holder.iv_icon.setBackgroundDrawable(appinfo.getIcon());
            holder.tv_name.setText(appinfo.getName());

            if (isLock) {
                holder.iv_lock.setBackgroundResource(R.drawable.lock);
            } else {
                holder.iv_lock.setBackgroundResource(R.drawable.unlock);
            }
             return convertView;
        }
    }

其中getView()方法中用了convertView和holderView來優化Listview,這已經是模板代碼了。所以具體的HolderView就不貼出來了 。

==========================================
下面這個部分單獨拎出來記錄:
當我們在“未加鎖”界面點擊右邊的小鎖時候,我們希望達到這樣的一種效果:我們點擊的這一個條目產生一個動畫效果,向右邊滑出,然後消失,在“已加鎖”界面顯示出我們方才點擊的哪一個條目

按照這種思路,我們首先弄一個執行動畫的類:

/**
     * 初始化平移動畫,平移自身寬度
     *
     * @param
     * @return
     * @author zfy
     * @created at 2016/6/26 10:56
     */
    private void initAnimation() {
        mTranslateAnimation = new TranslateAnimation(
                Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, 1,
                Animation.RELATIVE_TO_SELF, 0,
                Animation.RELATIVE_TO_SELF, 0);
        mTranslateAnimation.setDuration(500);

    }

接下來我們在Adapter 的getView()方法中,監聽holder.iv_lock這個圖標 的點擊事件:下面就是我一開始犯錯誤的地方了:

            final View finalConvertView = convertView;
            holder.iv_lock.setOnClickListener(new   View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //添加動畫效果
                    finalConvertView.startAnimation(mTranslateAnimation);
              if (isLock) {
                                //由已加鎖------>未加鎖
                                //添加動畫效果
                                //1.已加鎖的集合要刪除一個,未加鎖的幾個要增加一個
                                mLockList.remove(appinfo);
                                mUnlockList.add(appinfo);
                                //2.從已加鎖的數據庫中刪除一條數據
                                mDao.delete(appinfo.getPackageName());
                                //3.通知adapter刷新
                                mLockAdapter.notifyDataSetChanged();
                            } else {
                                //未加鎖----->已加鎖

                                //1.未加鎖的集合要刪除一個,已加鎖的幾個要增加一個
                                mLockList.add(appinfo);
                                mUnlockList.remove(appinfo);
                                //2.從已加鎖的數據庫中刪除一條數據
                                mDao.insert(appinfo.getPackageName());
                                //3.通知adapter刷新
                                mUnlockAdapter.notifyDataSetChanged();
                            }

一切都是這麼的水到渠成,點擊加鎖按鈕–>開啟動畫–>從未加鎖集合中刪除–>添加到已加鎖集合中–>添加到數據庫–>通知adapter刷新。
但是我忽略了一個問題,當我執行平移動畫的時候(500ms),下面對集合的操作,更新Adapter的操作就已經在執行了,並且已經執行完了。所以最終實現的動畫效果是,我點了一個條目,但是發生平移動畫的卻是下一個條目。這一點困惑了很久!所以我在這裡對動畫做了一個監聽:當動畫執行完了,才接著行對集合,數據庫,和adapter刷新的操作!!

final View finalConvertView = convertView;
            holder.iv_lock.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //添加動畫效果
                    finalConvertView.startAnimation(mTranslateAnimation);
                    //對動畫執行的效果做監聽,要監聽到動畫執行完成之後,再去移除集合中數據,操作數據庫,刷新界面
                    mTranslateAnimation.setAnimationListener(new Animation.AnimationListener() {
                        @Override
                        public void onAnimationStart(Animation animation) {

                        }

                        @Override //動畫結束後回調方法
                        public void onAnimationEnd(Animation animation) {
                            if (isLock) {
                                //由已加鎖------>未加鎖
                                //添加動畫效果
                                //1.已加鎖的集合要刪除一個,未加鎖的幾個要增加一個
                                mLockList.remove(appinfo);
                                mUnlockList.add(appinfo);
                                //2.從已加鎖的數據庫中刪除一條數據
                                mDao.delete(appinfo.getPackageName());
                                //3.通知adapter刷新
                                mLockAdapter.notifyDataSetChanged();
                            } else {
                                //未加鎖----->已加鎖

                                //1.未加鎖的集合要刪除一個,已加鎖的幾個要增加一個
                                mLockList.add(appinfo);
                                mUnlockList.remove(appinfo);
                                //2.從已加鎖的數據庫中刪除一條數據
                                mDao.insert(appinfo.getPackageName());
                                //3.通知adapter刷新
                                mUnlockAdapter.notifyDataSetChanged();
                            }


                        }

                        @Override
                        public void onAnimationRepeat(Animation animation) {

                        }
                    });


                }
            });

最終寫成這個樣子,就完全沒有問題了。

2.5對最上方兩個按鈕的處理

  bt_unlock.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1.已加鎖列表隱藏,未加鎖列表顯示
                ll_lock.setVisibility(View.GONE);
                ll_unlock.setVisibility(View.VISIBLE);
                //2.按鈕顏色切換
                bt_lock.setBackgroundResource(R.drawable.tab_right_default);
                bt_unlock.setBackgroundResource(R.drawable.tab_left_pressed);

            }
        });
        bt_lock.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //1.已加鎖列表顯示,未加鎖列表隱藏
                ll_lock.setVisibility(View.VISIBLE);
                ll_unlock.setVisibility(View.GONE);
                //2.按鈕顏色切換
                bt_lock.setBackgroundResource(R.drawable.tab_right_pressed);
                bt_unlock.setBackgroundResource(R.drawable.tab_left_default);

            }
        });

比較簡單,就不作說明了。

2.6分別設置Adapter

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //接收到消息,填充已加鎖和未加鎖的數據適配器
            mLockAdapter = new myAdapter(true);
            lv_lock.setAdapter(mLockAdapter);

            mUnlockAdapter = new myAdapter(false);
            lv_unlock.setAdapter(mUnlockAdapter);


        }
    };

這也是常規寫法,不做說明

三. 後記

到這裡就已經可以實現程序鎖的界面展示效果了,但是具體的業務邏輯還沒有處理, 只是一個空架子。
由於明天還有《數字信號處理》的抽考,今天還要復習,所以業務邏輯這一塊,留到考試考完再記錄。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved