样式图:
自定义dialog的布局文件layout_code_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="180dp"
android:layout_height="90dp"
android:layout_gravity="center"
android:background="@drawable/code_view_bg_shape"
android:orientation="vertical"
android:paddingTop="5dp">
<EditText
android:cursorVisible="false"
android:id="@+id/edt_code_input"
android:layout_width="80dp"
android:gravity="center"
android:layout_height="40dp"
android:layout_marginTop="2dp"
android:layout_marginLeft="10dp"
android:background="@drawable/code_view_input_bg_shape"
/>
<mchenys.net.csdn.blog.pcbaby_v8_testdemo.view.CodeView
android:id="@+id/code_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/edt_code_input"
android:layout_marginLeft="10dp"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/edt_code_input" />
<TextView
android:id="@+id/tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/code_view"
android:layout_below="@+id/code_view"
android:text="点击图片更换"
android:textSize="10sp" />
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/edt_code_input"
android:layout_marginTop="5dp"
android:background="#66666666" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/view_line">
<Button
android:id="@+id/btn_cancle"
android:textSize="15sp"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:gravity="center"
android:text="取消" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#66666666" />
<Button
android:id="@+id/btn_sure"
android:textSize="15sp"
android:textColor="#029AFF"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:gravity="center"
android:text="确定" />
</LinearLayout>
</RelativeLayout>
其中背景图片code_view_bg_shape和code_view_input_bg_shape是/drawable目录下创建的shape的xml文件.
分别为:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#fff" />
<corners android:radius="10dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#66666666"
/>
</shape>
mchenys.net.csdn.blog.pcbaby_v8_testdemo.view.CodeView是一个自定义的验证码控件,代码如下:
package mchenys.net.csdn.blog.pcbaby_v8_testdemo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
import java.util.Random;
/**
* Created by mChenys on 2015/12/1.
*/
public class CodeView extends View implements View.OnClickListener {
private static final char[] CHARS = {
'2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
//variables
private String code;
private Random random = new Random();
private int codeLength;//个数
private float fontSize;//字体大小
private Paint mTextPaint;//字体的画笔
private int paddingLeft;//左内边距
private int paddingTop;//上内边距
public void setCodeLength(int codeLength) {
this.codeLength = codeLength;
}
public String getCode() {
return code;
}
public CodeView(Context context) {
this(context, null);
}
public CodeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CodeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
codeLength = 4;
paddingLeft = dp2px(8);
paddingTop = dp2px(5);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextSize(25);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
fontSize = mTextPaint.getTextSize();//字体大小
System.out.println("fontSize px:" + fontSize);
mTextPaint.setTextAlign(Paint.Align.CENTER);//字体居中
code = createCode();//初始化的时候先生存code值,否则调用getCode()方法返回将是null
//设置点击监听
setOnClickListener(this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//左右边距+字体的字间距(这里字间距用fontSize代替)
int width = (int) (2 * paddingLeft + (codeLength - 1) * fontSize);
//上下边距+字体的高度
int height = (int) (2 * paddingTop + fontSize);
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.parseColor("#F2F2F2"));
System.out.println("onDraw code is :" + code);
char[] codeChar = code.toCharArray();
int fontX = 0; //每个字的X坐标
for (int i = 0; i < codeChar.length; i++) {
fontX = (int) (paddingLeft + i * fontSize);
String text = codeChar[i] + "";
canvas.drawText(text, fontX, paddingTop + fontSize, mTextPaint);
}
}
private String createCode() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < codeLength; i++) {
sb.append(CHARS[random.nextInt(CHARS.length)]);
}
return sb.toString();
}
/**
* dp转px
*
* @param dp
* @return
*/
private int dp2px(float dp) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5f);
}
/**
* sp to px
*/
public int sp2px(float sp) {
float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (sp * fontScale + 0.5f);
}
//点击回调方法里面处理验证码的更新
@Override
public void onClick(View v) {
code = createCode();//重新生成新的验证码
invalidate(); //刷新界面UI,会调用onDraw方法
if (null != listener) {
listener.OnChange(getCode());//通过自定义的监听接口返回新的验证码给调用者
}
}
//验证码变化的监听器
public interface OnCodeChangeListener {
void OnChange(String code);
}
private OnCodeChangeListener listener;
public void setOnCodeChangeListener(OnCodeChangeListener listener) {
this.listener = listener;
}
}
使用例子如下:
/**
* Created by mChenys on 2015/11/30.
*/
public class TextActivity extends Activity {
private String inputCode; //用户输入的验证码值
private String verificationCode;//图片显示的验证码值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text);
}
public void showCodeView(View view) {
final Dialog dialog = new Dialog(TextActivity.this, R.style.myDialog);
dialog.setContentView(R.layout.layout_code_dialog);
//提示信息
final TextView tvInfo = (TextView) dialog.findViewById(R.id.tv_info);
CodeView codeView = (CodeView) dialog.findViewById(R.id.code_view);
final EditText edtInput = (EditText) dialog.findViewById(R.id.edt_code_input);
//用户输入的验证码
inputCode = edtInput.getText().toString().trim();
//验证码图片显示的code
verificationCode = codeView.getCode();
codeView.setOnCodeChangeListener(new CodeView.OnCodeChangeListener() {
@Override
public void OnChange(String code) {
//点击验证码图片需要更新code值
verificationCode = code;
}
});
//确定按钮
dialog.findViewById(R.id.btn_sure).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
inputCode = edtInput.getText().toString().trim();
//校验验证码
if (TextUtils.isEmpty(inputCode)) {
tvInfo.setText("请输入验证码!");
} else if (!verificationCode.equalsIgnoreCase(inputCode)) {
tvInfo.setText("验证码错误");
} else {
//校验成功
dialog.dismiss();
}
}
});
//取消按钮
dialog.findViewById(R.id.btn_cancle).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
}
其中TextActivity的布局文件就是一个button,设置onClick="showCodeView"的属性:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0f0"
android:padding="20dp">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="showCodeView" />
</RelativeLayout>
输入验证的码提示的2种状态:
1.未输入的情况下,点击确定,提示"请输入验证码!"
2.输入错误,提示"验证码错误"