程序员人生 网站导航

Android---程序锁(1)展示页面的搭建

栏目:综合技术时间:2016-07-08 16:26:48

1.写在前面的话

在平常使用手机的进程中,我们常常希望有这样1个功能:可以对我们的某1个利用加锁,进入的时候需要输入密码验证身份,然后才可以进入主界面,这就是1个程序锁的功能。其实这类功能其实不难实现,正好在我最近随着黑马74期视频敲的1个大的Demo里有这1块的内容,所以决定记录1下实现的方式。纯记录。。

2.界面显示逻辑

2.1界面效果图
这里写图片描述
这里写图片描述

2.2layout布局文件
这里我们将“未加锁”和“已加锁”两个模块的ListView写在同1个布局文件中,用android:visibility=”“ 属性结合上方按钮的选中来决定下方是显示哪个ListView
布局文件代码以下:

<?xml version="1.0" encoding="utf⑻"?> <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"> <Button android:id="@+id/bt_unlock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/tab_left_pressed" android:text="未加锁" android:textColor="#fff" android:textSize="18sp"/> <Button android:id="@+id/bt_lock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/tab_right_default" android:text="已加锁" android:textColor="#fff" android:textSize="18sp"/> </LinearLayout> <LinearLayout android:id="@+id/ll_unlock" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv_unlock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="未加锁利用"/> <ListView android:id="@+id/lv_unlock" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </LinearLayout> <LinearLayout android:id="@+id/ll_lock" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="gone"> <TextView android:id="@+id/tv_lock" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="未加锁利用"/> <ListView android:id="@+id/lv_lock" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </LinearLayout> </LinearLayout>

注意到@+id/ll_lock android:visibility=”gone”,也就是通过对这两个属性的改变来控制下方的ListView到底显示的是哪个。

2.3ListView的数据来源
有了ListView我们自然就会想到,LIstView始终需要两个部份,数据源和数据适配器,也就是Adapter。首先我记录1下展现数据的来源。

//辨别已加锁利用和未加锁的利用 private void initData() { new Thread(new Runnable() { @Override public void run() { //1.获得手机中所有的利用 mAppInfoList = appInfoProvider.getAppInfoList(getApplicationContext()); //2.辨别已加锁利用和未加锁利用 mLockList = new ArrayList<AppInfo>(); mUnlockList = new ArrayList<AppInfo>(); //3.获得数据库中已加锁利用包名的集合 mDao = appLockDao.getInstance(getApplicationContext()); List<String> 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();
这3个是我已封装好的方法,分别用于拿得手机中所有的利用;拿到岁数据库增删改查的对象;拿到目前数据库中已有的数据。
这个意思就是说,我将已加锁的利用放到数据库中,然后将已加锁和未加锁的利用分别放到两个集合中:mLockList,mUnlockList。由于拿数据这个操作可能耗时,所以我们将这个方法放到线程中去履行。最后在利用消息机制通知主线程,数据已准备好。

2.4Adapter的设置

由于我们将两个ListVIew都写在同1个布局里,所以我们也用1个Adapter同时去配置两个LIstView,只是加上1个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就不贴出来了 。

==========================================
下面这个部份单独拎出来记录:
当我们在“未加锁”界面点击右侧的小锁时候,我们希望到达这样的1种效果:我们点击的这1个条目产生1个动画效果,向右侧滑出,然后消失,在“已加锁”界面显示出我们方才点击的哪个条目

依照这类思路,我们首先弄1个履行动画的类:

/** * 初始化平移动画,平移本身宽度 * * @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这个图标 的点击事件:下面就是我1开始出错误的地方了:

final View finalConvertView = convertView; holder.iv_lock.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //添加动画效果 finalConvertView.startAnimation(mTranslateAnimation); if (isLock) { //由已加锁------>未加锁 //添加动画效果 //1.已加锁的集合要删除1个,未加锁的几个要增加1个 mLockList.remove(appinfo); mUnlockList.add(appinfo); //2.从已加锁的数据库中删除1条数据 mDao.delete(appinfo.getPackageName()); //3.通知adapter刷新 mLockAdapter.notifyDataSetChanged(); } else { //未加锁----->已加锁 //1.未加锁的集合要删除1个,已加锁的几个要增加1个 mLockList.add(appinfo); mUnlockList.remove(appinfo); //2.从已加锁的数据库中删除1条数据 mDao.insert(appinfo.getPackageName()); //3.通知adapter刷新 mUnlockAdapter.notifyDataSetChanged(); }

1切都是这么的瓜熟蒂落,点击加锁按钮–>开启动画–>从未加锁集合中删除–>添加到已加锁集合中–>添加到数据库–>通知adapter刷新。
但是我疏忽了1个问题,当我履行平移动画的时候(500ms),下面对集合的操作,更新Adapter的操作就已在履行了,并且已履行完了。所以终究实现的动画效果是,我点了1个条目,但是产生平移动画的却是下1个条目。这1点困惑了很久!所以我在这里对动画做了1个监听:当动画履行完了,才接着行对集合,数据库,和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.已加锁的集合要删除1个,未加锁的几个要增加1个 mLockList.remove(appinfo); mUnlockList.add(appinfo); //2.从已加锁的数据库中删除1条数据 mDao.delete(appinfo.getPackageName()); //3.通知adapter刷新 mLockAdapter.notifyDataSetChanged(); } else { //未加锁----->已加锁 //1.未加锁的集合要删除1个,已加锁的几个要增加1个 mLockList.add(appinfo); mUnlockList.remove(appinfo); //2.从已加锁的数据库中删除1条数据 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); } };

这也是常规写法,不做说明

3. 后记

到这里就已可以实现程序锁的界面展现效果了,但是具体的业务逻辑还没有处理, 只是1个空架子。
由于明天还有《数字信号处理》的抽考,今天还要温习,所以业务逻辑这1块,留到考试考完再记录。

PS: 《数字信号处理》 这门课也是够了。整本书的傅里叶变换,离散傅里叶变换,快速傅里叶变化,Z变换,逆Z变换……TM的 ~
上次写的Widget那片文章,不知道为何,竟然1晚上有2000多人阅读。。是我的 错觉吗?我这个渣渣的技术博客1篇文章竟然访问量这么高。 还是最近很多人在学这1块的实现?
不管为何,这也让我更加坚定,坚持写技术博客的决心!

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐