編輯:關於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);
}
};
這也是常規寫法,不做說明
到這裡就已經可以實現程序鎖的界面展示效果了,但是具體的業務邏輯還沒有處理, 只是一個空架子。
由於明天還有《數字信號處理》的抽考,今天還要復習,所以業務邏輯這一塊,留到考試考完再記錄。
獲取域ID和方法ID均分別需要域描述符合方法描述符,域描述符合方法描述符都可以通過下表中的Java類型簽名映射獲得。
據說Android最推薦的是在ViewPager中使用FragMent,即ViewPager中的頁面不像前面那樣用LayoutInflater直接從布局文件加載,而是一個
上一篇文章中我們講解了Android中的幾種常見網絡協議:xml,json,protobuf等,以及各自的優缺點,一般而言主要我們的App涉及到了網絡傳輸都會有這方面的內
先看看效果圖: 第一篇Tab系列的文章首先實現這種風格的底部Tab:背景條顏色不變,我們是用了深灰的顏色,圖標會發生相應的變化,當選中某個標簽後該標簽的背