目的
在一些app中往往采用一些比较好玩的或者说可爱的动画登录界面来加深用户对app的印象,然后我们一般都会想这么有趣的东西这是怎么实现的呢?下面即将对一个当用户输密码时猫头鹰捂眼睛的动画进行实现。
要实现的主要功能
1.用户点击输入用户名时界面不动
2.点击输入密码栏时,猫头鹰翅膀向上捂住眼睛
具体实现
1.容器改为RelativeLayout,将要用的图片添加到xml文件中的res->drawable下面,添加背景图片,在添加之前,先在res->values->style里面隐藏ActionBar,即将ActionBar改成NoActionBar,再添加,接下来添加虚化层。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--添加背景图片-->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/bg"
android:scaleType="fitXY"/>
<!--添加虚化层-->
<io.alterac.blurkit.BlurLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:blk_fps="0"
app:blk_blurRadius="1"
/>
</RelativeLayout>
app:blk_fps=""如果只有一张图片可以将这个功能设为0,即一帧
导⼊虚化功能的第三⽅库
在build.gradle中添加:implementation 'io.alterac.blurkit:blurkit:1.1.0'
并将SDK改为21,然后点击Sync now同步
2.设置输入框背景,因为用到shape的一些功能,所以在drawable->Drawable resourse file里面新建一个xml文件来实现
将selector改为shape,设置其为rectangle,圆角,颜色
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp"/>
<solid android:color="#44666666"/>
</shape>
在activity_main.xml里添加输入框背景
<!--输入框背景-->
<io.alterac.blurkit.BlurLayout
android:id="@+id/bg"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@drawable/input_bg_shape"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:blk_fps="0"/>
3.添加标题和输入框视图,设置其相应属性,接着添加标题和输入框以及按钮的相关操作
LinearLayout:线性布局,即从容器左端开始布局
orientation:即表示你要横向(vertical)还是竖向(horizontal)设置
<!--添加标题和输入框视图-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_centerInParent="true"
android:orientation="vertical"
android:padding="20dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp">
<!--标题-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:textColor="#999999"
android:textSize="20dp"
android:textAlignment="center"/>
<!--添加输入框-->
<EditText
android:id="@+id/et_user"
style="@style/EdittextStyle"
android:drawableLeft="@drawable/iconfont_user"
android:hint="请输入用户名"
android:inputType="text"
/>
<EditText
android:id="@+id/et_password"
style="@style/EdittextStyle"
android:drawableLeft="@drawable/iconfont_password"
android:hint="请输入密码"
android:inputType="textPassword" />
<!--添加按钮-->
<Button
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="登录"
android:textColor="#999999"
android:layout_marginTop="20dp"
android:enabled="false"
android:background="@drawable/login_btn_selector"/>
</LinearLayout>
添加输入框时,由于有很多属性是它们共有的,因此和上面创建时同理,创建一个xml文件来管理,在values下面创建,设置属性。需要时直接通过style来找
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--app中的标题:字体 字号 颜色-->
<style name="EdittextStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">50dp</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:drawable">@drawable/ic_launcher_background</item>
<item name="android:paddingLeft">7dp</item>
<item name="android:drawablePadding">7dp</item>
<item name="android:textSize">20sp</item>
<item name="android:maxLines">1</item>
</style>
</resources>
在drawable里创建一个xml文件同上,配置输入框的shape,可以从上面的添加输入框里看到添加了两个输入框,其中hint为默认输入的字体,设置文本的类型用InputType
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp"/>
<stroke android:width="1dp"
android:color="#666666"/>
</shape>
同上在drawable里创建一个xml文件设置按钮的selector,之后在LinearLayout里添加按钮
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--无法点击状态 灰色背景 圆角矩形-->
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#666666"/>
</shape>
</item>
<!--正常状态 蓝色背景 圆角矩形-->
<item >
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#39A4F9"/>
</shape>
</item>
</selector>
4.在MainActivity里面获取xml中的控件,并为输⼊框添加内容和焦点改变的事件
public class MainActivity extends AppCompatActivity implements TextWatcher {
private EditText user;
private EditText password;
private Button loginBtn;
private ImageView leftArm;
private ImageView rightArm;
private ImageView leftHand;
private ImageView rightHand;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
public void initViews(){
user=findViewById(R.id.et_user);
password=findViewById(R.id.et_password);
loginBtn =findViewById(R.id.bt_login);
leftArm=findViewById(R.id.iv_left_arm);
rightArm=findViewById(R.id.iv_right_arm);
leftHand=findViewById(R.id.iv_left_hand);
rightHand=findViewById(R.id.iv_right_hand);
//监听内容改变:控制按钮的点击状态
user.addTextChangedListener(this);
password.addTextChangedListener(this);
//监听EditText的焦点变化->控制是否需要捂住眼睛
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus==true){
//捂住
close();
}else {
//打开
open();
}
}
});
}
}
监听touch事件,触摸屏幕,隐藏键盘,相应的输⼊框失去焦点
/**
* 当有控件获得焦点focus 自动弹出键盘
* 1.点击软件盘的enter 自动收回
* 2.代码控制 InputMethodManager
* ShowSoftInout显示键盘 必须先让这个view成为焦点requestFocus
* hideSoftInputFromWindow隐藏键盘
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_DOWN){
//隐藏键盘
//1.获取系统输入的管理器
InputMethodManager inputManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
//2.隐藏键盘
inputManager.hideSoftInputFromWindow(user.getWindowToken(),0);
//3.取消焦点
View focusView=getCurrentFocus();
if (focusView!=null) {
focusView.clearFocus();//取消焦点
}
// focusView.requestFocus();//请求焦点
//getCurrentFocus().clearFocus();
}
return true;
}
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
//判断两个输入框是否有内容
if (user.getText().toString().length()>0&&password.getText().toString().length()>0){
//按钮可以点击
loginBtn.setEnabled(true);
}else{
//按钮不能点击
loginBtn.setEnabled(false);
}
}
使⽤相对布局在xml里管理猫头鹰头、⼿掌、翅膀视图
<!--添加猫头鹰-->
<RelativeLayout
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_alignTop="@id/bg"
android:layout_marginTop="-116dp">
<!--头像-->
<ImageView
android:id="@+id/iv_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/owl_head"
android:layout_centerHorizontal="true"/>
<!--手掌-->
<ImageView
android:id="@+id/iv_left_hand"
android:layout_width="75dp"
android:layout_height="80dp"
android:src="@drawable/icon_hand"
android:layout_alignParentLeft="true"
android:layout_alignBottom="@id/iv_head"
android:layout_marginBottom="-34dp"/>
<ImageView
android:id="@+id/iv_right_hand"
android:layout_width="75dp"
android:layout_height="80dp"
android:src="@drawable/icon_hand"
android:layout_alignParentRight="true"
android:layout_alignBottom="@id/iv_head"
android:layout_marginBottom="-34dp"/>
<!--翅膀-->
<ImageView
android:id="@+id/iv_left_arm"
android:layout_width="80dp"
android:layout_height="50dp"
android:src="@drawable/arm_left"
android:layout_below="@id/iv_head"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
/>
<ImageView
android:id="@+id/iv_right_arm"
android:layout_width="80dp"
android:layout_height="50dp"
android:src="@drawable/arm_right"
android:layout_below="@id/iv_head"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"/>
</RelativeLayout>
在res->Directory下创建anim⽂件夹
再创建向上移动和向下移动的动画,上下里面内容相同
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:toYDelta="100"
android:fromYDelta="0"
android:fillAfter="true"
android:duration="500">
</translate>
再回到MainActivity里
实现捂住眼睛,左右⼿旋转上去
public void close(){
//旋转翅膀
RotateAnimation lAnim=new RotateAnimation(0,165,leftArm.getWidth(),0f);
lAnim.setDuration(500);
lAnim.setFillAfter(true);
leftArm.startAnimation(lAnim);
RotateAnimation rAnim=new RotateAnimation(0,-165,0f,0f);
rAnim.setDuration(500);
rAnim.setFillAfter(true);
rightArm.startAnimation(rAnim);
TranslateAnimation down=(TranslateAnimation) AnimationUtils.loadAnimation(this,R.anim.hand_down_anim);
leftHand.startAnimation(down);
rightHand.startAnimation(down);
}
⼿臂打开,左右⼿旋转下去
public void open(){
//旋转翅膀
RotateAnimation lAnim=new RotateAnimation(165,0,leftArm.getWidth(),0f);
lAnim.setDuration(500);
lAnim.setFillAfter(true);
leftArm.startAnimation(lAnim);
RotateAnimation rAnim=new RotateAnimation(-165,0,0f,0f);
rAnim.setDuration(500);
rAnim.setFillAfter(true);
rightArm.startAnimation(rAnim);
TranslateAnimation up=(TranslateAnimation) AnimationUtils.loadAnimation(this,R.anim.hand_up_anim);
leftHand.startAnimation(up);
rightHand.startAnimation(up);
}