<?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>
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();
}
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;
}
@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();
}
}
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);
}
}
}
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);
}
}
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;
}
@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);
}
}
<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>
@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;
}
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();
/**
* 根据等差数列公式an=a1+(n-1)*d,我们知道an跟a1,n=(an的列或者行值-a1的列或者行值+1),
* 算出d,如果d为整数那么为等差数列,如果an的列或者行值-a1的列或者行值>1的话,就证明存在
* 中间值。
* 1、算出的d是否为整数
* 2、an的行值-a1的行值>1或者an的列值-a1的列值>1
*
* 两个条件成立的话就证明有中间点
*/
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;
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有