您的位置:首页 > 其它

自定义View——仿支付宝支付弹窗界面

2017-07-16 10:51 681 查看


上面这个是采用自定view方式实现的一个仿支付宝支付弹窗的效果;

1、自定义view并初始化自定义属性

public class PasswordEditText extends EditText{
//一个密码所占的宽度
private int mPasswordItemWidth;
//密码的个数默认6个
private int mPasswordNumder=6;
//背景边框颜色
private int mBgColor= Color.parseColor("#d1d2d6");
//背景边框的大小
private int mBgSize=1;
//背景边框圆角大小
private int mBgCorner=0;
//分割线的颜色
private int mDivisionLineColor=mBgColor;
//分割线的大小
private int mDivisionLineSize=1;
//密码圆点的颜色
private int mPasswordColor=mDivisionLineColor;
//密码圆点的半径大小
private int mPasswordRadius=4;
public PasswordEditText(Context context) {
this(context,null);
}
public PasswordEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initAttributeSet(context, attrs);

}
/**
* 初始化属性
* @param context
* @param attrs
*/
private void initAttributeSet(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);
//获取大小
mDivisionLineSize= (int) array.getDimension(R.styleable.PasswordEditText_divisionLineSize,dip2px(mDivisionLineSize));
mPasswordRadius= (int) array.getDimension(R.styleable.PasswordEditText_passwordRadius,dip2px(mPasswordRadius));
mBgSize= (int) array.getDimension(R.styleable.PasswordEditText_bgSize,dip2px(mBgSize));
mBgCorner= (int) array.getDimension(R.styleable.PasswordEditText_bgCorner,dip2px(mBgCorner));
//获取颜色
mBgColor=array.getColor(R.styleable.PasswordEditText_bgColor,mBgColor);
mDivisionLineColor=array.getColor(R.styleable.PasswordEditText_divisionLineColor,mDivisionLineColor);
mPasswordColor=array.getColor(R.styleable.PasswordEditText_passwordColor,mDivisionLineColor);
array.recycle();
}
}


继承自EditText的话可以用使用EditText中的一些属性和方法,在初始化完自定义属性后要记得调用recycle()方法进行回收;

2、初始化画笔

/**
* 初始化画笔
*/
private void initPaint() {
mPaint=new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}


在第三个构造函数中调用就可以了,

3、在onDraw()方法中进行绘制

在绘制的时候先要计算出一个密码所占的宽度

//一个密码的宽度
private int mPasswordItemWidth=(getWidth()-2*mBgSize-(mPasswordNumder-1)*mDivisionLineSize)/mPasswordNumder;


一个密码的宽度=(整个输入框的宽度-(最左边边框的宽度+最右边边框的宽度)-(密码个数-1)*密码之间分割线的宽度)/密码的个数


获取到一个密码的宽度后就可以进行绘制;

3.1、绘制密码输入框的背景

private void drawBg(Canvas canvas) {
RectF rect=new RectF(mBgSize,mBgSize,getWidth()-mBgSize,getHeight()-mBgSize);
//绘制背景  如果有圆角就绘制圆角矩形,没有就绘制矩形
//设置画笔的大小
mPaint.setStrokeWidth(mBgSize);
mPaint.setColor(mBgColor);
//绘制空心
mPaint.setStyle(Paint.Style.STROKE);
if(mBgCorner==0){
canvas.drawRect(rect,mPaint);
}else{
canvas.drawRoundRect(rect,mBgCorner,mBgCorner,mPaint);
}
}


没有圆角的话,就调用canvas.drawRect(rect,mPaint);绘制矩形,第一个参数是RectF对象,第二个参数是Paint(画笔);

/* @param left   The X coordinate of the left side of the rectangle
* @param top    The Y coordinate of the top of the rectangle
* @param right  The X coordinate of the right side of the rectangle
* @param bottom The Y coordinate of the bottom of the rectangle
*/
public RectF(float left, float top, float right, float bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}


RectF源码对四个参数都有说明;

left=输入框边框的大小;
top=输入框边框的大小;
right=getWidth()-输入框边框的大小;
bottom=getHeight()-输入框边框的大小;


如果有圆角的话,就调用canvas.drawRoundRect(rect,mBgCorner,mBgCorner,mPaint);绘制圆角矩形,

/**
* @param rect  The rectangular bounds of the roundRect to be drawn
* @param rx    The x-radius of the oval used to round the corners
* @param ry    The y-radius of the oval used to round the corners
* @param paint The paint used to draw the roundRect
*/
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
}


drawRoundRect源码也对要传入的参数做了说明;

3.2、绘制密码输入框之间的分割线

private void drawDivisionLine(Canvas canvas) {
mPaint.setStrokeWidth(mDivisionLineSize);
mPaint.setColor(mDivisionLineColor);
for (int i=0;i<mPasswordNumder-1;i++){
int startX=mBgSize+(i+1)*mPasswordItemWidth+i*mDivisionLineSize;
int startY=mBgSize;
int endX=startX;
int endY=getHeight()-mBgSize;
canvas.drawLine(startX,startY,endX,endY,mPaint);

}
}


在绘制分割线的时候需要注意,假设密码的个数是6,只需要绘制5个分割线,调用canvas.drawLine(startX,startY,endX,endY,mPaint);方法进行绘制,

/**
* @param startX The x-coordinate of the start point of the line
* @param startY The y-coordinate of the start point of the line
* @param paint  The paint used to draw the line
*/
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
}


上面是drawLine方法的源码,第一个参数是X的起始位置,第二个参数是Y的起始位置,第三个参数是X的终点位置,第四个参数是Y的终点位置;

startX=输入框边框的宽度+(每个密码的宽度)*当前绘制的位置(当前绘制第几个)+单个分割线的宽度*当前绘制的位置(当前绘制第几个);
startY=输入框边框的宽度;
stopX=startX;
stopY=getHeight()-输入框边框的宽度;


3.3、绘制密码

private void drawPassword(Canvas canvas) {
//设置实心样式
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mPasswordColor);
String text=getText().toString().trim();
int passwordLength=text.length();
for(int i=0;i<passwordLength;i++){
int cx=mBgSize+i*mPasswordItemWidth+i*mDivisionLineSize+mPasswordItemWidth/2;
int cy=getHeight()/2;
canvas.drawCircle(cx,cy,mPasswordRadius,mPaint);
}
}


在绘制密码黑圆点之前先要获取到输入的字符的长度,根据长度遍历该字符串调用canvas.drawCircle(cx,cy,mPasswordRadius,mPaint);进行绘制,

drawCircle()源码:

/**
* @param cx     The x-coordinate of the center of the cirle to be drawn
* @param cy     The y-coordinate of the center of the cirle to be drawn
* @param radius The radius of the cirle to be drawn
* @param paint  The paint used to draw the circle
*/
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
}


第一个参数是X的位置,第二个参数是Y的位置,第三个参数是圆的半径,第四个参数是画笔;

cx=输入框边框的宽度+单个分割线的宽度*当前绘制哪一个+密码框的宽度*当前绘制哪一个+密码框的宽度/2;
cy=getHeight()/2;


到这里输入框背景、分割线、密码都已经绘制完毕了,在这里面添加一个密码添加和删除的方法;

/**
* 设置密码
* @param numder
*/
public void addPassword(String numder) {
//把之前的密码取出来
String password=getText().toString().trim();
//判断密码的长度,不能超过当前设置的密码的个数
if(password.length()>=mPasswordNumder){
return;
}
//密码叠加
password+=numder;
setText(password);
}


/**
* 删除最后一位密码
*/
public void deleteLastPassword() {
//把之前的密码取出来
String password=getText().toString().trim();
//判断当前密码是否为空
if(TextUtils.isEmpty(password)){
return;
}
password=password.substring(0,password.length()-1);
setText(password);
}


剩下还有键盘没有弄好,键盘的实现是在xml布局里面写好,添加到LinearLayout中;

4、输入键盘的实现

public class CustomerKeyboard extends LinearLayout implements View.OnClickListener {
public CustomerKeyboard(Context context) {
this(context,null);
}

public CustomerKeyboard(Context context, AttributeSet attrs) {
this(context, attrs,0);
}

public CustomerKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//直接加载布局
inflate(context,R.layout.ui_customer_keyboard,this);
}
}


添加进来后,设置相应的点击事件;

/**
* 设置点击事件
* @param view
*/
private void setItemClickListener(View view) {
if(view instanceof ViewGroup){
ViewGroup viewGroup= (ViewGroup) view;
int childCount = viewGroup.getChildCount();
for (int i=0;i<childCount;i++){
View childView = viewGroup.getChildAt(i);
setItemClickListener(childView);
}
}else{
view.setOnClickListener(this);
}
}


@Override
public void onClick(View v) {
if(v instanceof TextView){
//点击的是文本
String number=((TextView) v).getText().toString().trim();
if(mListener!=null&&number.length()!=0){
mListener.click(number);
}
}
if(v instanceof ImageView){
//点击的是删除
if(mListener!=null){
mListener.delete();
}
}
}


差不多效果就实现了,在点击的地方调用就可以了;

//弹出dialog输入框
AlertDialog dialog=new AlertDialog.Builder(this).
setContentView(R.layout.activity_main).
fullWith().
formBottom(true).
setCancelable(true).
show();
passwordEditText=dialog.getView(R.id.password);
mCustomerKeyboard=dialog.getView(R.id.customer_keyboard);

mCustomerKeyboard.setOnCustomerKeyboardClickListener(this);
passwordEditText.setEnabled(false);
passwordEditText.setOnPasswordFullListener(this);


源码地址:

http://download.csdn.net/download/wangwo1991/9894467
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  自定义View 弹窗