大家在使用bilibili等應用時,常見到類似的一些操作,在輸入密碼時,貓頭鷹將手臂旋轉遮住自己的眼鏡,這個功能比較有意思,這里代碼主要就是實現這個功能
app效果展示:

app外部展示

進入后界面

輸入密碼時遮住眼睛
xml文件配置:
使用相對布局
<?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="25" />
<!--貓頭鷹-->
<RelativeLayout
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_alignTop="@+id/iv_bg"
android:layout_marginTop="-100dp">
<!--頭像-->
<ImageView
android:id="@+id/iv_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/owl_headre"
android:layout_centerHorizontal="true"/>
<!--手掌-->
<ImageView
android:id="@+id/iv_left_hand"
android:layout_width="50dp"
android:layout_height="60dp"
android:src="@drawable/icon_hand"
android:layout_alignParentLeft="true"
android:layout_alignBottom="@id/iv_head"
android:layout_marginBottom="-20dp"
android:layout_marginLeft="10dp"/>
<!--手掌-->
<ImageView
android:id="@+id/iv_right_hand"
android:layout_width="50dp"
android:layout_height="60dp"
android:src="@drawable/icon_hand"
android:layout_alignParentRight="true"
android:layout_alignBottom="@id/iv_head"
android:layout_marginBottom="-20dp"
android:layout_marginRight="10dp"/>
<!--翅膀-->
<ImageView
android:id="@+id/iv_left_arm"
android:layout_width="65dp"
android:layout_height="40dp"
android:src="@drawable/arm_left"
android:layout_below="@+id/iv_head"
android:layout_alignParentLeft="true"
android:layout_marginLeft="20dp"/>
<!--翅膀-->
<ImageView
android:id="@+id/iv_right_arm"
android:layout_width="65dp"
android:layout_height="40dp"
android:src="@drawable/arm_right"
android:layout_below="@+id/iv_head"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"/>
</RelativeLayout>
<!--輸入背景框-->
<io.alterac.blurkit.BlurLayout
android:id="@+id/iv_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" />
<!--添加標題和輸入框視圖-->
<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:inputType="text"
android:hint="請輸入用戶名" />
<EditText
android:id="@+id/et_password"
style="@style/EditTextStyle"
android:inputType="textPassword"
android:hint="請輸入密碼" />
<!--添加按鈕-->
<Button
android:id="@+id/bt_login"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="登錄"
android:textColor="#ffffff"
android:layout_marginTop="30dp"
android:enabled="false"
android:background="@drawable/login_btn_selector"/>
</LinearLayout>
</RelativeLayout>
一層一層將控件加上去
另外,我們希望對背景圖片進行虛化,具體的虛化操作如下:

找到這里
implementation 'io.alterac.blurkit:blurkit:1.1.0'

加入對應代碼
然后右上方彈出:

點擊同步即可
然后可能會報錯,報錯將對應的安卓版本改為21;

更改版本為21
相應資源文件管理:

anim
hand_down_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>
hand_up_anim內部代碼:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:toYDelta="0"
android:fromYDelta="100"
android:fillAfter="true"
android:duration="500">
</translate>

drawable
editview_shape內部代碼:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5sp"/>
<stroke android:width="1dp"
android:color="#44000000"/>
</shape>
input_bg_shape內部代碼:
<?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>
login_btn_selector內部代碼:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--無法點擊狀態(tài) 灰色背景 圓角矩形-->
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#666666"/>
</shape>
</item>
<!--正常狀態(tài) 藍色背景 圓角矩形-->
<item >
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="#39A4F9"/>
</shape>
</item>
</selector>
設置共有屬性(這樣我們同樣的屬性就不需要反復的去設置,只要導用相應的樣式即可)

共有屬性
<?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:background">@drawable/editview_shape</item>
<item name="android:layout_marginTop">20dp</item>
<item name="android:drawableLeft">@drawable/iconfont_user</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>
主程序中代碼:
package swu.twj.a7_covereyelogin;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
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);
//監(jiān)聽內容改變 -> 控制按鈕的點擊狀態(tài)
user.addTextChangedListener(this);
password.addTextChangedListener(this);
//監(jiān)聽EditText的焦點變化 -> 控制是否需要捂住眼睛
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFoucus) {
if (hasFoucus == true){
//旋轉手臂
close();
//捂住眼睛
Toast t = Toast.makeText(getApplicationContext(),"捂住眼睛",Toast.LENGTH_SHORT);
t.show();
}else {
//旋轉手臂
open();
//打開
Toast.makeText(getApplicationContext(),"放手",Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 當有控件獲得焦點focus 自動彈出鍵盤
* 1.點擊軟鍵盤的enter鍵 自動收回鍵盤
* 2.代碼控制 InputMethodManager
* requestFocus
* showSoftInput:顯示鍵盤 必須先讓這個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(); //取消焦點
}
//getCurrentFocus().clearFocus();
//focusView.requestFocus(); //請求焦點
}
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);
}
}
public void close(){
//旋轉翅膀(左)
RotateAnimation lAnim = new RotateAnimation(0,167,leftArm.getWidth(),0f);
lAnim.setDuration(500);
lAnim.setFillAfter(true);
leftArm.startAnimation(lAnim);
//旋轉翅膀(右)
RotateAnimation rAnim = new RotateAnimation(0,-167,0,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(167,0,leftArm.getWidth(),0f);
lAnim.setDuration(500);
lAnim.setFillAfter(true);
leftArm.startAnimation(lAnim);
//旋轉翅膀(右)
RotateAnimation rAnim = new RotateAnimation(-167,0,0,0f);
rAnim.setDuration(500);
rAnim.setFillAfter(true);
rightArm.startAnimation(rAnim);
}
}