最近在网上看到了一个比较不错的登录界面,效果如下图:
是不是很好玩;后来研究了一下,主要是通过自定义的View加上动画实现的,先看代码:
首先是自定义View:
public class OwlView extends View {
private Context mContext;
private Bitmap bm_owl;
private Bitmap bm_owl_arm_left;
private Bitmap bm_owl_arm_right;
private int bm_height;
private int moveHeight;
private int alpha = 255;
private int move_length = 0;
private Paint handPaintBefore;
private Paint handPaintAfter;
public OwlView(Context context) {
this(context, null);
}
public OwlView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public OwlView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
init();
}
private void init() {
setBackgroundColor(Color.TRANSPARENT);
getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
ViewGroup.LayoutParams lp = getLayoutParams();
if (lp == null)
return;
lp.width = dip2px(175);
lp.height = dip2px(107);
setLayoutParams(lp);
setTranslationY(dip2px(9));
}
});
bm_owl = BitmapFactory.decodeResource(getResources(),
R.drawable.owl_login);
bm_owl_arm_left = BitmapFactory.decodeResource(getResources(),
R.drawable.owl_login_arm_left);
bm_owl_arm_right = BitmapFactory.decodeResource(getResources(),
R.drawable.owl_login_arm_right);
bm_owl = compressBitmap(bm_owl, dip2px(115), dip2px(107), false);
bm_owl_arm_left = compressBitmap(bm_owl_arm_left, dip2px(40),
dip2px(65), true);
bm_owl_arm_right = compressBitmap(bm_owl_arm_right, dip2px(40),
dip2px(65), true);
bm_height = bm_owl_arm_left.getHeight() / 3 * 2 - dip2px(10);
handPaintBefore = new Paint();
handPaintBefore.setColor(Color.parseColor("#472d20"));
handPaintBefore.setAntiAlias(true);
handPaintAfter = new Paint();
handPaintAfter.setAntiAlias(true);
}
public void close() {
ValueAnimator alphaVa = ValueAnimator.ofInt(0, 255).setDuration(300);
alphaVa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
alpha = (Integer) animation.getAnimatedValue();
invalidate();
}
});
alphaVa.start();
ValueAnimator moveVa = ValueAnimator.ofInt(dip2px(45), 0).setDuration(
200);
moveVa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
move_length = (Integer) animation.getAnimatedValue();
invalidate();
}
});
moveVa.setStartDelay(200);
moveVa.start();
ValueAnimator va = ValueAnimator.ofInt(bm_height, 0).setDuration(300);
va.setInterpolator(new LinearInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
moveHeight = (Integer) animation.getAnimatedValue();
invalidate();
}
});
va.start();
}
public void open() {
final ValueAnimator alphaVa = ValueAnimator.ofInt(255, 0).setDuration(
300);
alphaVa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
alpha = (Integer) animation.getAnimatedValue();
invalidate();
}
});
alphaVa.start();
ValueAnimator moveVa = ValueAnimator.ofInt(0, dip2px(45)).setDuration(
200);
moveVa.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
move_length = (Integer) animation.getAnimatedValue();
invalidate();
}
});
moveVa.start();
ValueAnimator va = ValueAnimator.ofInt(0, bm_height).setDuration(300);
va.setInterpolator(new LinearInterpolator());
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
moveHeight = (Integer) animation.getAnimatedValue();
invalidate();
}
});
va.setStartDelay(100);
va.start();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(
bm_owl,
new Rect(0, 0, bm_owl.getWidth(), bm_owl.getHeight()),
new Rect(dip2px(30), 0, dip2px(30) + bm_owl.getWidth(), bm_owl
.getHeight()), handPaintAfter);
handPaintBefore.setAlpha(alpha);
canvas.drawOval(new RectF(moveHeight, getHeight() - dip2px(20),
move_length + dip2px(30), getHeight()), handPaintBefore);
canvas.drawOval(
new RectF(getWidth() - dip2px(30) - move_length, getHeight()
- dip2px(20), getWidth() - move_length, getHeight()),
handPaintBefore);
canvas.drawBitmap(bm_owl_arm_left,// Bitmap
new Rect(0,// left
0,// top
bm_owl_arm_left.getWidth(),// right
moveHeight),// bottom
new Rect(dip2px(43), getHeight() - moveHeight - dip2px(10),
dip2px(43) + bm_owl_arm_left.getWidth(), getHeight()
- dip2px(9)), handPaintAfter);// Paint
// canvas.drawBitmap(Bitmap,Rect,Rect,Paint)
canvas.drawBitmap(bm_owl_arm_right,// Bitmap
new Rect(0,// left
0,// top
bm_owl_arm_right.getWidth(),// right
moveHeight),// bottom
new Rect(getWidth() - dip2px(40) - bm_owl_arm_right.getWidth(),// left
getHeight() - moveHeight - dip2px(10),// top
getWidth() - dip2px(40),// right
getHeight() - dip2px(9)),// bottom
handPaintAfter);// Paint
}
/**
* 压缩图片
*
* @param bitmap
* @param reqsW
* @param reqsH
* @param isAdjust
* @return
*/
private Bitmap compressBitmap(Bitmap bitmap, int reqsW, int reqsH,
boolean isAdjust) {
if (bitmap == null || reqsW == 0 || reqsH == 0)
return bitmap;
if (bitmap.getWidth() > reqsW || bitmap.getHeight() > reqsH) {
/**
* BigDecimal用法详解
*
* 由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,
* 可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
* 以利用BigDecimal对货币和百分比格式化为例
* 。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用
* ,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比。
*/
float scaleX = new BigDecimal(reqsW).divide(
new BigDecimal(bitmap.getWidth()), 4, RoundingMode.DOWN)
.floatValue();
float scaleY = new BigDecimal(reqsH).divide(
new BigDecimal(bitmap.getHeight()), 4, RoundingMode.DOWN)
.floatValue();
if (isAdjust) {
scaleX = scaleX < scaleY ? scaleX : scaleY;
scaleY = scaleX;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleX, scaleY);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
bitmap.getHeight(), matrix, true);
}
return bitmap;
}
private int dip2px(int dpValue) {
float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
然后界面:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#008ECB" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_marginTop="107dp"
android:background="@drawable/bg_layout">"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="140dp"
android:orientation="vertical" >
<EditText
android:id="@+id/uname"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="@drawable/bg_edittext"
android:hint="请输入账号"
android:paddingLeft="10dp" />
<EditText
android:id="@+id/upwd"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:password="true"
android:background="@drawable/bg_edittext"
android:hint="请输入密码"
android:paddingLeft="10dp" />
</LinearLayout>
</FrameLayout>
<com.example.logindemo.OwlView
android:id="@+id/owl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal" >
</com.example.logindemo.OwlView>
</FrameLayout>
最后就是在activity里给两个Editext加监听了:
public class MainActivity extends Activity {
private EditText uname, upwd;
private OwlView owl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uname = (EditText) findViewById(R.id.uname);
upwd = (EditText) findViewById(R.id.upwd);
owl = (OwlView) findViewById(R.id.owl);
uname.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if (hasFocus) {
owl.close();
}
}
});
upwd.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if (hasFocus) {
owl.open();
}
}
});
}
}
附上项目下载地址:http://download.csdn.net/detail/stephenzml/9889642