我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android手势密码view学习笔记(二)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android手势密码view学习笔记(二)

我们还是接着我们上一篇博客中的内容往下讲哈,上一节 Android手势密码view笔记(一)我们已经实现了我们的IndicatorView指示器view了:

下面我们来实现下我们的手势密码view:

实现思路:

1、我们照样需要拿到用户需要显示的一些属性(行、列、选中的图片、未选中的图片、错误显示的图片、连接线的宽度跟颜色......)。

2、我们需要根据手势的变换然后需要判断当前手指位置是不是在某个点中,在的话就把该点设置为选中状态,然后每移动到两个点(也就是一个线段)就记录该两个点。

3、最后把记录的所有点(所有线段)画在canvas上,并记录每个点对应的num值(也就是我们设置的密码)。

4、当手指抬起的时候,执行回调方法,把封装的密码集合传给调用着。
好啦~ 既然右了思路,我们就来实现下:

首先是定义一个attrs.xml文件(为了方便,我就直接在上一篇博客中实现的indicatorview的attr里面继续往下定义了):


<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="IndicatorView">
  <!--默认状态的drawable-->
  <attr name="normalDrawable" format="reference" />
  <!--被选中状态的drawable-->
  <attr name="selectedDrawable" format="reference" />
  <!--列数-->
  <attr name="column" format="integer" />
  <!--行数-->
  <attr name="row" format="integer" />
  <!--错误状态的drawabe-->
  <attr name="erroDrawable" format="reference" />
  <!--padding值,padding值越大点越小-->
  <attr name="padding" format="dimension" />
  <!--默认连接线颜色-->
  <attr name="normalStrokeColor" format="color" />
  <!--错误连接线颜色-->
  <attr name="erroStrokeColor" format="color" />
  <!--连接线size-->
  <attr name="strokeWidth" format="dimension" />
 </declare-styleable>
</resources>

然后就是第一个叫GestureContentView的view去继承viewgroup,并重新三个构造方法:


public class GestureContentView extends ViewGroup {
 public void setGesturePwdCallBack(IGesturePwdCallBack gesturePwdCallBack) {
  this.gesturePwdCallBack = gesturePwdCallBack;
 }
 public GestureContentView(Context context) {
  this(context, null);
 }
 public GestureContentView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 public GestureContentView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  }
}

然后我们需要在带三个参数的构造方法中获取我们传入的自定义属性:


public GestureContentView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  setWillNotDraw(false);
  obtainStyledAttr(context, attrs, defStyleAttr);
  initViews();
 }

你会发现我这里调用下setWillNotDraw(false);方法,顾名思义,设置为false后onDraw方法才会被调用,当然你也可以重写dispatchDraw方法(具体原因我就不扯了哈,自己网上查或者看view的源码)。


private void obtainStyledAttr(Context context, AttributeSet attrs, int defStyleAttr) {
  final TypedArray a = context.obtainStyledAttributes(
    attrs, R.styleable.IndicatorView, defStyleAttr, 0);
  mNormalDrawable = a.getDrawable(R.styleable.IndicatorView_normalDrawable);
  mSelectedDrawable = a.getDrawable(R.styleable.IndicatorView_selectedDrawable);
  mErroDrawable = a.getDrawable(R.styleable.IndicatorView_erroDrawable);
  checkDrawable();
  if (a.hasValue(R.styleable.IndicatorView_row)) {
   mRow = a.getInt(R.styleable.IndicatorView_row, NUMBER_ROW);
  }
  if (a.hasValue(R.styleable.IndicatorView_column)) {
   mColumn = a.getInt(R.styleable.IndicatorView_row, NUMBER_COLUMN);
  }
  if (a.hasValue(R.styleable.IndicatorView_padding)) {
   DEFAULT_PADDING = a.getDimensionPixelSize(R.styleable.IndicatorView_padding, DEFAULT_PADDING);
  }
  strokeColor=a.getColor(R.styleable.IndicatorView_normalStrokeColor,DEFAULT_STROKE_COLOR);
  erroStrokeColor=a.getColor(R.styleable.IndicatorView_erroStrokeColor,ERRO_STROKE_COLOR);
  strokeWidth=a.getDimensionPixelSize(R.styleable.IndicatorView_strokeWidth,DEFAULT_STROKE_W);
 }

然后获取到了我们需要的东西后,我们需要知道每个点的大小跟自己的大小了(还是一样的套路,不懂的看上一篇博客哈):


@Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  float width = MeasureSpec.getSize(widthMeasureSpec);
  float height = MeasureSpec.getSize(heightMeasureSpec);
  float result = Math.min(width, height);
  height = getHeightValue(result, heightMode);
  width = getWidthValue(result, widthMode);
  setMeasuredDimension((int) width, (int) height);
 }

 private float getHeightValue(float height, int heightMode) {
  if (heightMode == MeasureSpec.EXACTLY) {
   mCellHeight = (height - (mColumn + 1) * DEFAULT_PADDING) / mColumn;
  } else {
   mCellHeight = Math.min(mNormalDrawable.getIntrinsicHeight(), mSelectedDrawable.getIntrinsicHeight());
   height = mCellHeight * mColumn + (mColumn + 1) * DEFAULT_PADDING;
  }
  return height;
 }
 private float getWidthValue(float width, int widthMode) {
  if (widthMode == MeasureSpec.EXACTLY) {
   mCellWidth = (width - (mRow + 1) * DEFAULT_PADDING) / mRow;
  } else {
   mCellWidth = Math.min(mNormalDrawable.getIntrinsicWidth(), mSelectedDrawable.getIntrinsicWidth());
   width = mCellWidth * mRow + (mRow + 1) * DEFAULT_PADDING;
  }
  return width;
 }

好了,view的大小跟点的大小我们都知道了,然后我们需要根据我们传入的行数跟列数添加我们的点了:


@Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  if (!isInitialed && getChildCount() == 0) {
   isInitialed = true;
   points = new ArrayList<>();
   addChildViews();
  }
 }

首先在onSizeChanged方法中去添加我们的点(也就是子view)因为onSizeChanged会被调很多次,然后避免重复添加子view,我们做了一个判断,第一次并且child=0的时候再去添加子view:


 private void addChildViews() {
  for (int i = 0; i < mRow; i++) {
   for (int j = 0; j < mColumn; j++) {
    GesturePoint point = new GesturePoint();
    ImageView image = new ImageView(getContext());
    point.setImageView(image);
    int left = (int) ((j + 1) * DEFAULT_PADDING + j * mCellWidth);
    int top = (int) ((i + 1) * DEFAULT_PADDING + i * mCellHeight);
    int right = (int) (left + mCellWidth);
    int bottom = (int) (top + mCellHeight);
    point.setLeftX(left);
    point.setRightX(right);
    point.setTopY(top);
    point.setBottomY(bottom);
    point.setCenterX((int) (left + mCellWidth / 2));
    point.setCenterY((int) (top + mCellHeight / 2));
    point.setNormalDrawable(mNormalDrawable);
    point.setErroDrawable(mErroDrawable);
    point.setSelectedDrawable(mSelectedDrawable);
    point.setState(PointState.POINT_STATE_NORMAL);
    point.setNum(Integer.parseInt(String.valueOf(mRow * i + j)));
    point.setPointX(i);
    point.setPointY(j);
    this.addView(image, (int) mCellWidth, (int) mCellHeight);
    points.add(point);
   }
  }
 }

添加的个数=行数*列数,然后把创建的image添加进当前viewgroup中:


for (int i = 0; i < mRow; i++) {
   for (int j = 0; j < mColumn; j++) {
    GesturePoint point = new GesturePoint();
    ImageView image = new ImageView(getContext());
  ......
   this.addView(image, (int) mCellWidth, (int) mCellHeight);
 }
}

并且把所有的点信息存放在了一个叫points.add(point);的集合中,集合中存放的是GesturePoint对象:


public class GesturePoint {
 //点的左边距值
 private int leftX;
 //点的top值
 private int topY;
 //点的右边距值
 private int rightX;
 private int bottomY;
 //点的中间值x轴
 private int centerX;
 private int centerY;
 //点对应的行值
 private int pointX;
 //点对应的列值
 private int pointY;
 //点对应的imageview
 private ImageView imageView;
 //当前点的状态:选中、未选中、错误
 private PointState state;
 //当前点对应的密码数值
 private int num;
 //未选中点的drawale
 private Drawable normalDrawable;
 private Drawable erroDrawable;
 private Drawable selectedDrawable;
 }

既然我们已经添加了很多个点,然后我们要做的就是根据行列排列我们点的位置了(重写onLayout方法摆放子view(点)的位置):


@Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
  if (points != null && points.size() > 0) {
   for (GesturePoint point : points) {
    point.layout();
   }
  }
 }

public void layout() {
  if (this.imageView != null) {
   this.imageView.layout(leftX, topY, rightX, bottomY);
  }
 }

然后我们添加下我们的view并运行代码:


<FrameLayout
  android:layout_width="match_parent"
  android:layout_height="0dp"
  android:layout_weight="1"
  android:layout_marginTop="10dp"
  >
  <com.leo.library.view.GestureContentView
   android:id="@+id/id_gesture_pwd"
   android:layout_gravity="center_horizontal"
   android:layout_marginTop="10dp"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:column="3"
   app:row="3"
   app:padding="50dp"
   app:normalDrawable="@drawable/gesture_node_normal"
   app:selectedDrawable="@drawable/gesture_node_pressed"
   app:erroDrawable="@drawable/gesture_node_wrong"
   app:normalStrokeColor="#000"
   app:erroStrokeColor="#ff0000"
   app:strokeWidth="4dp"
   />
 </FrameLayout>

效果图:

写到这里,离我们的目标越来越近了,接下来要做的就是重写onTouchEvent方法,然后通过手指滑动位置做出相应的改变了:

1、我们需要根据手指的位置查看是否在某个点内,判断该点是不是被选中,没选中就改变其状态为选中状态。

2、手指每连接两个点的时候,我们需要判断两个点中间是否有点,比如:我们手指连接了(0,0) 跟(2,2)这两个点,那么我们需要判断中间是否有点(1、1)存在。然后需要把线段(0,0)~(1、1)和线段(1、1)~(2、2)保存在集合中,然后下一次再画线段的时候起点就为(2、2)点了。

3、没选中一个点我们就把该点对应的num值(密码)存入集合中。

4、当执行ACTION_UP事件(也就是手指抬起的时候),回调方法,把存储的集合数据传给调用者。


 @Override
 public boolean onTouchEvent(MotionEvent event) {
  //是否允许用户绘制
  if (!isDrawEnable) return super.onTouchEvent(event);
  //画笔颜色设置为绘制颜色
  linePaint.setColor(strokeColor);
  int action = event.getAction();
  //当手指按下的时候
  if (MotionEvent.ACTION_DOWN == action) {
   //清除画板
   changeState(PointState.POINT_STATE_NORMAL);
   preX = (int) event.getX();
   preY = (int) event.getY();
   //根据当前手指位置找出对应的点
   currPoint = getPointByPosition(preX, preY);
   //如果当前手指在某个点中的时候,把该点标记为选中状态
   if (currPoint != null) {
    currPoint.setState(PointState.POINT_STATE_SELECTED);
    //把当前选中的点添加进集合中
    pwds.add(currPoint.getNum());
   }
   //当手指移动的时候
  } else if (MotionEvent.ACTION_MOVE == action) {
   //,清空画板,然后画出前面存储的线段
   clearScreenAndDrawLine();
   //获取当前移动的位置是否在某个点中
   GesturePoint point = getPointByPosition((int) event.getX(), (int) event.getY());
   //没有在点的范围内的话并且currpoint也为空的时候(在画板外移动手指)直接返回
   if (point == null && currPoint == null) {
    return super.onTouchEvent(event);
   } else {
    //当按下时候的点为空,然后手指移动到了某一点的时候,把该点赋给currpoint
    if (currPoint == null) {
     currPoint = point;
     //修改该点的状态
     currPoint.setState(PointState.POINT_STATE_SELECTED);
     //添加该点的值
     pwds.add(currPoint.getNum());
    }
   }
   //当移动的不在点范围内、一直在同一个点中移动、选中了某个点后再次选中的时候不让选中(也就是不让出现重复密码)
   if (point == null || currPoint.getNum() == point.getNum() || point.getState() == PointState.POINT_STATE_SELECTED) {
    lineCanvas.drawLine(currPoint.getCenterX(), currPoint.getCenterY(), event.getX(), event.getY(), linePaint);
   } else {
    //修改该点的状态为选中
    point.setState(PointState.POINT_STATE_SELECTED);
    //连接currpoint跟当前point
    lineCanvas.drawLine(currPoint.getCenterX(), currPoint.getCenterY(), point.getCenterX(), point.getCenterY(), linePaint);
    //判断两个点中是否存在点
    List<Pair<GesturePoint, GesturePoint>> betweenPoints = getBetweenPoints(currPoint, point);
    //如果存在点的话,把中间点对应的线段存入集合总
    if (betweenPoints != null && betweenPoints.size() > 0) {
     pointPairs.addAll(betweenPoints);
     currPoint = point;
     pwds.add(point.getNum());
    } else {
     pointPairs.add(new Pair(currPoint, point));
     pwds.add(point.getNum());
     currPoint = point;
    }
   }
   invalidate();
  } else if (MotionEvent.ACTION_UP == action) {
   //手指抬起的时候回调
   if (gesturePwdCallBack != null) {
    List<Integer> datas=new ArrayList<>(pwds.size());
    datas.addAll(pwds);
    gesturePwdCallBack.callBack(datas);
   }
  }
  return true;
 }

重点解释下getBetweenPoints方法(声明一下哈:本人数学比较差,有好方法的童鞋虐过哈。记得评论告诉我一下,拜谢啦~~ 自己觉得自己的方法比较蠢,嘻嘻~!!):


 private List<Pair<GesturePoint, GesturePoint>> getBetweenPoints(GesturePoint currPoint, GesturePoint point) {
  //定义一个集合装传入的点
  List<GesturePoint> points1 = new ArrayList<>();
  points1.add(currPoint);
  points1.add(point);
  //排序两个点
  Collections.sort(points1, new Comparator<GesturePoint>() {
   @Override
   public int compare(GesturePoint o1, GesturePoint o2) {
    return o1.getNum() - o2.getNum();
   }
  });
  GesturePoint maxPoint = points1.get(1);
  GesturePoint minPoint = points1.get(0);
  points1.clear();
  
  if (((maxPoint.getNum() - minPoint.getNum()) % Math.max(maxPoint.getPointX(), maxPoint.getPointY()) == 0)
    &&
    ((maxPoint.getPointX() - minPoint.getPointX()) > 1 ||
      maxPoint.getPointY() - minPoint.getPointY() > 1
    )) {
   //算出等差d
   int duration = (maxPoint.getNum() - minPoint.getNum()) / Math.max(maxPoint.getPointX(), maxPoint.getPointY());
   //算出中间有多少个点
   int count = maxPoint.getPointX() - minPoint.getPointX() - 1;
   count = Math.max(count, maxPoint.getPointY() - minPoint.getPointY() - 1);
   //利用等差数列公式算出中间点(an=a1+(n-1)*d)
   for (int i = 0; i < count; i++) {
    int num = minPoint.getNum() + (i + 1) * duration;
    for (GesturePoint p : this.points) {
     //在此判断算出的中间点是否存在并且没有被选中
     if (p.getNum() == num && p.getState() != PointState.POINT_STATE_SELECTED) {
      //把选中的点添加进集合
      pwds.add(p.getNum());
      //修改该点的状态为选中状态
      p.setState(PointState.POINT_STATE_SELECTED);
      points1.add(p);
     }
    }
   }
  }
  //利用算出的中间点来算出中间线段
  List<Pair<GesturePoint, GesturePoint>> pairs = new ArrayList<>();
  for (int i = 0; i < points1.size(); i++) {
   GesturePoint p = points1.get(i);
   if (i == 0) {
    pairs.add(new Pair(minPoint, p));
   } else if (pairs.size() > 0) {
    pairs.add(new Pair(pairs.get(0).second, p));
   }
   if (i == points1.size() - 1) {
    pairs.add(new Pair(p, maxPoint));
   }
  }
  //返回中间线段
  return pairs;
 }

好啦!!代码就解析到这里了哈,看不懂的童鞋自己去拖代码然后跑跑就知道了。

整个做下来除了某几个地方有点难度外,其它的地方也都是很简单的东西呢?以前看起来很高大上的东西是不是现在觉得soeasy了呢?? 哈哈~~~

最后给出项目github链接:
https://github.com/913453448/GestureContentView

您可能感兴趣的文章:Android手势密码的实现Android自定义控件实现手势密码Android自定义UI手势密码终结版Android仿支付宝手势密码解锁功能Android手势密码实现实例代码Android九宫格手势密码代码设计Android自定义UI手势密码改进版源码下载Android自定义UI手势密码简单版Android手势密码view学习笔记(一)Android自定义View手势密码


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android手势密码view学习笔记(二)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android手势密码view学习笔记(二)

我们还是接着我们上一篇博客中的内容往下讲哈,上一节 Android手势密码view笔记(一)我们已经实现了我们的IndicatorView指示器view了:下面我们来实现下我们的手势密码view:实现思路: 1、我们照样需要拿到用户需要显示
2022-06-06

Android手势密码view学习笔记(一)

刚接触Android的时候看到别人写的手势密码view,然后当时就在想,我什么时候才能写出如此高端的东西?? 没关系,不要怕哈,说出这样话的人不是你技术不咋地而是你不愿意花时间去研究它,其实也没有那么难哦(世上无难事,只怕有心人!),下面我
2022-06-06

android学习笔记之View的滑动

Android开发中我们常常需要View滑动实现一些绚丽的效果来优化用户体验,下面这篇文章主要给大家介绍了关于android学习笔记之View滑动的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-01-03

Android学习笔记——Menu介绍(二)

知识点: 这次将继续上一篇文章没有讲完的Menu的学习,上下文菜单(Context menu)和弹出菜单(Popup menu)。 上下文菜单 上下文菜单提供对UI界面上的特定项或上下文框架的操作,就如同Windows中右键菜单一样。 在A
2022-06-06

第一行代码—Android第二版学习笔记

Android 第一行代码学习笔记第一章 概述1.1安卓系统架构1.2Android四大组件1.3项目结构1.4app目录结构1.5 项目运行原理1.6 res目录详解1.7日志工具的使用第二章 活动2.1 创建基本活动2.2 使用Inte
2022-06-06

Android学习笔记(二)之电话拨号器

目前Android已经在只能手机市场已经具有强大的霸主地位,也吸引了越来越多的追捧者。Android的学习也越来越火。但是,报名费用确实大多人望而却步 一、新建项目CallPhone 1.1、建立项目 二、设置界面与项目名称 2.1、更
2022-06-06

Android学习笔记(二)App工程文件分析

App工程文件分析 关于如何创建一个最简单的Android App请参照链接: 《 Android学习笔记(一)环境安装及第一个hello world 》 //www.jb51.net/article/52593.htm 创建完的工程文件如
2022-06-06

Android学习笔记(十二)——数据存储(SQLite数据库)

【第一部分】历史文章: Android学习笔记(一)——创建第一个Android项目 Android学习笔记(二)android studio基本控件及布局(实现图片查看器) Android学习笔记(三)android studio中Che
2022-06-06

Android学习笔记--Activity中使用Intent传值示例代码

Intent,又称为意图,是一种运行时绑定机制,它能在程序运行的过程中链接两个不同的组件(Activity、Service、BroadcastReceiver)。通过Intent,程序可以向Android表达某种请求或意愿,Android会
2022-06-06

如何在Android中利用view实现一个手势密码功能

这篇文章将为大家详细讲解有关如何在Android中利用view实现一个手势密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。用法:
2023-05-31

Android学习笔记--通过Application传递数据代码示例

在整个Android程序中,有时需要保存某些全局的数据(如:用户信息),方便在程序的任何地方调用。在Activity之间数据传递中有一种比较使用的方式,就是全局对象,使用过J2EE的都应该知道JavaWeb的四个作用域,其中Applicat
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录