Android 一个美观简洁的登录界面
一.登录式样1:
1.效果图:
2.布局代码:
<?xml version="1.0" encoding="utf-8"?>
<!--登录界面,用LinearLayout-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/wallpaper_11"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="35dp">
<ImageView
android:id="@+id/symbol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:layout_marginLeft="20dp"
android:id="@+id/qq"
android:layout_width="wrap_content"
android:layout_marginTop="35dp"
android:text="仿QQ"
android:textColor="@color/white"
android:textSize="24sp"
android:layout_height="wrap_content" />
</LinearLayout>
<!--输入框-->
<EditText
android:id="@+id/et_user_name"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingLeft="10dp"
android:theme="@style/MyEditText"
android:drawablePadding="@dimen/dp_10"
android:drawableLeft="@mipmap/msg_icon"
android:textColor="@color/white"
android:textColorHint="@color/white"
android:layout_marginTop="60dp"
android:hint="账号"
android:textSize="20sp" />
<!--输入框-->
<EditText
android:id="@+id/et_psw"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:hint="密码"
android:drawablePadding="@dimen/dp_10"
android:drawableLeft="@mipmap/msg_icon"
android:textColor="@color/white"
android:paddingLeft="10dp"
android:theme="@style/MyEditText"
android:textColorHint="@color/white"
android:textSize="20sp"
android:inputType="textPassword"/>
<!--按钮-->
<Button
android:id="@+id/btn_login"
android:text="登录"
android:background="#1E90FF"
android:textSize="24sp"
android:textColor="@color/white"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:layout_width="320dp"
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_marginTop="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_register"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:textColor="@color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="新用户注册"/>
<!--layout_weight="1" layout_width="0dp"实现均分效果-->
<TextView
android:id="@+id/tv_find_psw"
android:layout_alignParentLeft="true"
android:layout_marginLeft="20dp"
android:textColor="@color/white"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="忘记密码?" />
</RelativeLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_gravity="center"
android:layout_marginBottom="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:textColor="@color/white"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录即代表阅读并同意服务条款" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
3.设置AppCompatEditText(EditText)的下划线和光标显示的颜色,自定义默认和选中的颜色设置:
在style中配置
<style name="MyEditText" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">@color/white</item>
<item name="colorControlActivated">@color/colorConfirm</item>
</style>
4.android:textCursorDrawable 自定义光标样式,设置为”@null”之后发现光标的样式会变得跟文字的颜色一样
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size android:width="2dp" />
<solid android:color="@android:color/holo_blue_light" />
</shape>
<EditText
android:textCursorDrawable="@drawable/cursor_color"
android:hint="自定义光标颜色"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
5.5.0一下的手机显示下划线可以会有问题,Material Design风格体现不出来,可以这样处理:
设置选择状态:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="false" android:drawable="@drawable/et_underline_unselected"/>
<item android:state_focused="true" android:drawable="@drawable/et_underline_selected"/>
</selector>
et_underline_unselected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape>
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="@android:color/darker_gray" />
<padding android:bottom="4dp" />
</shape>
</item>
</layer-list>
et_underline_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape>
<solid android:color="@android:color/transparent" />
<stroke
android:color="@android:color/holo_green_light"
android:width="2dp" />
<padding android:bottom="4dp" />
</shape>
</item>
</layer-list>
/**初始化EditText,默认都为未选中状态**/
editText1.setBackgroundResource(R.drawable.et_underline_unselected);
editText2.setBackgroundResource(R.drawable.et_underline_unselected);
/**第一个EditText的焦点监听事件**/
editText1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
Log.e(TAG, "EditText1获得焦点");
editText1.setBackgroundResource(R.drawable.et_underline_selected);
} else {
Log.e(TAG, "EditText1失去焦点");
editText1.setBackgroundResource(R.drawable.et_underline_unselected);
}
}
});
/**第二个EditText的焦点监听事件**/
editText2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
Log.e(TAG, "EditText2获得焦点");
editText2.setBackgroundResource(R.drawable.et_underline_selected);
} else {
Log.e(TAG, "EditText2失去焦点");
editText2.setBackgroundResource(R.drawable.et_underline_unselected);
}
}
});
二.登录式样2:
1.效果图:
2.布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".ui.activity.sgf.login.MyLoginActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/wallpaper_11"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="30dp"
android:paddingTop="20dp"
android:background="#99404348"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Welcome"
android:textColor="#FFFFFF"
android:textSize="18sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="20dp"
android:paddingTop="20dp"
android:background="#99000000">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:layout_gravity="center"
android:layout_marginRight="50dp"
android:layout_marginLeft="50dp"
android:textColor="#9F9FA0"
android:textColorHint="#9F9FA0"
android:hint="your username"/>
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="#83738F"
android:layout_marginRight="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="5dp"></View>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:layout_gravity="center"
android:hint="your password"
android:textColor="#9F9FA0"
android:textColorHint="#9F9FA0"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="30dp"
android:paddingTop="20dp"
android:background="#99404348"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Forget Password?"
android:textColor="#DDDDDD"
android:textSize="15sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Tap Here"
android:textColor="#FFFFFF"
android:textSize="15sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:background="@drawable/buttonstyle"
android:text="Login"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="40dp"
android:layout_marginLeft="10dp"
android:background="@drawable/buttonstyle"
android:layout_weight="1"
android:text="Sign in"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
圆角背景
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape>
<!-- 色值 -->
<solid android:color="#585EE0" />
<!-- 圆角 -->
<corners android:radius="10dp" />
</shape>
</item>
<item android:state_pressed="true">
<shape>
<!-- 色值 -->
<solid android:color="#289BE5" />
<!-- 圆角 -->
<corners android:radius="10dp" />
</shape>
</item>
</selector>
要是你想使用圆角背景渐变色的话可以看看下面:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#3A3C39"
android:endColor="#181818"
android:angle="270"
/>
<corners android:radius="0dp" />
</shape>
其中 android:angle="270" 代表方向, 270表示从上到下,180表示从右到左,默认从左
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="@color/colorPrimary"
android:startColor="@color/colorAccent" />
</shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:type="radial" android:gradientRadius="250"
android:startColor="#E9E9E9" android:endColor="#D4D4D4" />
</shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="0" android:startColor="#FFdaf3fc"
android:centerColor="#FFd4e9a9" android:endColor="#FFdaf3fc"/>
</shape>
在这里要注意android:type="radial"类型的使用会有不同的效果,android:centerColor="#FFd4e9a9" 通常这个也不是被人常用
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#FFACDAE5"
android:endColor="#FF72CAE1"
android:angle="45"
/>
</shape>
Android背景色渐变(左上->右下)
<gradient
android:angle="135"
android:centerColor="#4CAF50"
android:endColor="#2E7D32"
android:startColor="#81C784"
android:type="linear" />
在这里设置背景上下渐变色 设置背景左右渐变色都是可以的
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#509245" android:centerColor="#3e8532"
android:endColor="#509245" android:type="linear" android:angle="90"
android:centerX="0.5" android:centerY="0.5" />
<padding android:left="7dp" android:top="7dp" android:right="7dp"
android:bottom="7dp" />
<corners android:radius="4dp" />
</shape>
android:shape 配置的是图形的形式,主要包括方形、圆形等,上边代码为方形。gradient节点主要配置起点颜色、终点颜色、中间点的坐标、中间点的颜色、渐变角度(90度为上下渐变,0为左右渐变),padding节点主要配置上下左右边距,corners节点配置四周园角的半径。
三.登录式样三(EditText、TextInputLayout、AppCompatEditText、ClearEditText等)
1.布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--android.support.design:hintAnimationEnabled | 是否显示hint的动画,默认true-->
<!--android.support.design:hintEnabled | 是否使用hint属性,默认true-->
<!--android.support.design:hintTextAppearance | 设置hint的文字样式(指运行动画效果之后的样式)-->
<!--android.support.design:counterEnabled | 是否显示计数器-->
<!--android.support.design:counterMaxLength | 设置计数器的最大值-->
<!--android.support.design:counterOverflowTextAppearance | 输入字符大于我们限定个数字符时的样式-->
<!--app:theme 设置浮动标签的颜色主题-->
<!--EditText 设置左侧图片,系统建议drawableStart/drawableLeft一起用,API>17-->
<!--android.support.design:passwordToggleEnabled | 是否显示密码开关图片,需要EditText设置inputType-->
<!--android.support.design:passwordToggleTint | 设置密码开关图片颜色-->
<!--android.support.design:passwordToggleTintMode | 设置密码开关图片(混合颜色模式),与passwordToggleTint同时使用-->
<!--android.support.design:errorEnabled |是否显示错误信息-->
<!--android.support.design:errorTextAppearance| 错误信息的字体样式-->
<!--系统默认的密码开关(修改颜色主题)-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:theme="@style/CustomAppTheme_textinputLayout">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:theme="@style/CustomAppTheme_textinputLayout"
app:errorEnabled="true">
<com.hjq.widget.view.ClearEditText
android:id="@+id/et_email"
style="@style/MyEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入邮箱" />
</com.google.android.material.textfield.TextInputLayout>
<!--app:counterTextAppearance="@style/Mystyle"-->
<!--app:counterOverflowTextAppearance="@style/HintError"-->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:theme="@style/CustomAppTheme_textinputLayout"
app:counterEnabled="true"
app:counterMaxLength="5"
app:counterOverflowTextAppearance="@style/HintError"
app:counterTextAppearance="@style/Mystyle"
app:hintTextAppearance="@style/Mystyle"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/white">
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:inputType="textPassword"
android:textColor="@color/white"
android:textColorHint="@color/white" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:theme="@style/CustomAppTheme_textinputLayout"
app:counterEnabled="true"
app:counterMaxLength="6"
app:counterOverflowTextAppearance="@style/HintError"
app:counterTextAppearance="@style/Mystyle"
app:errorEnabled="true"
app:errorTextAppearance="@color/white"
app:hintTextAppearance="@style/Mystyle"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/white">
<EditText
android:id="@+id/et_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入验证码"
android:inputType="number"
android:textColor="@color/white"
android:textColorHint="@color/white" />
</com.google.android.material.textfield.TextInputLayout>
<!--验证码-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<!--android:background="@drawable/bg_edittext_selector"-->
<EditText
android:id="@+id/et_code2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:hint="请输入验证码"
android:inputType="number"
android:padding="10dp"
android:textColor="@color/white"
android:textColorHint="@color/white"
android:theme="@style/MyEditText" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"></RelativeLayout>
<TextView
android:id="@+id/tv_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_gravity="center|right"
android:layout_marginRight="20dp"
android:text="(60s)"
android:textColor="@color/white" />
</RelativeLayout>
<!--验证码-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<!--android:background="@drawable/bg_edittext_selector"-->
<EditText
android:id="@+id/et_code3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:hint="请输入验证码"
android:inputType="number"
android:padding="10dp"
android:textColor="@color/white"
android:textColorHint="@color/white"
android:theme="@style/MyEditText" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"></RelativeLayout>
<TextView
android:id="@+id/tv_code3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_gravity="center|right"
android:layout_marginRight="20dp"
android:text="X"
android:textColor="@color/white" />
</RelativeLayout>
<EditText
android:id="@+id/EditText2"
android:layout_width="fill_parent"
android:layout_height="36dip"
android:layout_below="@+id/EditText"
android:layout_margin="5dip"
android:background="@drawable/line3"
android:hint="请输入用户名"
android:padding="5dip"
android:singleLine="true"
android:textColorHint="#AAAAAA"
android:textSize="15dip" />
<EditText
android:id="@+id/EditText3"
android:layout_width="fill_parent"
android:layout_height="36dip"
android:layout_below="@+id/EditText2"
android:layout_margin="5dip"
android:background="@drawable/line3"
android:hint="自定义光标颜色"
android:digits="1234567890qwertyuiopasdfghjklzxcvbnm"
android:padding="5dip"
android:textCursorDrawable="@drawable/bg_edittext"
android:layerType="software"
android:singleLine="true"
android:textColorHint="#AAAAAA"
android:textSize="15dip" />
<Button
android:id="@+id/bt_yes"
android:text="确认"
android:textColor="@color/white"
android:textSize="18sp"
android:layout_gravity="center"
android:paddingLeft="120dp"
android:paddingRight="120dp"
android:background="@drawable/bt_blue"
android:layout_width="wrap_content"
android:layout_height="40dp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
2.属性:
<style name="MyEditText" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">@color/white</item>
<item name="colorControlActivated">@color/colorConfirm</item>
</style>
<style name="CustomAppTheme_textinputLayout" parent="Theme.AppCompat.Light.NoActionBar">
<!-- <item name="colorAccent">#3498db</item> -->
<item name="android:textColorHint">@color/gray</item>
<item name="colorControlNormal">@color/gray</item>
<item name="colorControlActivated">@color/colorAccent</item>
<item name="colorControlHighlight">@color/colorAccent</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
<!--输入框设置颜色-->
<style name="HintError" parent="TextAppearance.AppCompat">
<item name="android:textColor">@color/red</item>
</style>
<style name="Mystyle" >
<item name="android:textColor">#00aaff</item>
<item name="android:textSize">16sp</item>
</style>
bg_edittext.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--宽度-->
<size android:width="1dp" />
<!--色值-->
<solid android:color="#3399dd"/>
</shape>
bt_blue.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#0047CC" />
<corners android:radius="8dip"/>
<stroke
android:width="1dip"
android:color="#0047CC" />
</shape>
3.主函数代码:
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import com.example.m1571.mycolorfulnews.R;
import butterknife.ButterKnife;
/**
* 登录输入框
*/
public class TextInputLayoutActivity extends AppCompatActivity {
private TextInputLayout textinputlayout_email;
private TextInputLayout textinputlayout_name;
private TextInputLayout textinputlayout_password;
private TextInputLayout textinputlayout_code;
private EditText et_email;
private EditText et_name;
private EditText et_password;
private EditText et_code;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_textinputlayout);
ButterKnife.bind(this);
et_name = findViewById(R.id.et_name);
et_email = findViewById(R.id.et_email);
et_password = findViewById(R.id.et_password);
et_code = findViewById(R.id.et_code);
textinputlayout_name = findViewById(R.id.textinputlayout_name);
textinputlayout_email = findViewById(R.id.textinputlayout_email);
textinputlayout_password = findViewById(R.id.textinputlayout_password);
textinputlayout_code = findViewById(R.id.textinputlayout_code);
et_email.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// if (!RegexUtils.isEmail(charSequence)) {
// textInputLayout.setError("邮箱格式错误");
// textInputLayout.setErrorEnabled(true);
// } else {
// textInputLayout.setErrorEnabled(false);
// }
if (!isValidEmail(et_email.getText())) {
// edittext2.setError("Email is invalid");
// textInputLayout2.setError("Email is invalid");
textinputlayout_email.setError("邮箱格式错误");
textinputlayout_email.setErrorEnabled(true);
} else {
// textinputlayout_email.setError(null);
textinputlayout_email.setErrorEnabled(false);
}
//邮箱输入框清空后,颜色恢复默认
if (TextUtils.isEmpty(et_email.getText().toString().trim())) {
textinputlayout_email.setErrorEnabled(false);
}
if (charSequence.toString().length() < 1) {
textinputlayout_email.setErrorEnabled(false);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
et_email.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
if (!isValidEmail(et_email.getText())) {
// et_email.setError("Email is invalid");
// textInputLayout2.setError("Email is invalid");
} else {
// textInputLayout2.setError(null);
}
}
}
});
et_code.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// if (!RegexUtils.isEmail(charSequence)) {
// textInputLayout.setError("邮箱格式错误");
// textInputLayout.setErrorEnabled(true);
// } else {
// textInputLayout.setErrorEnabled(false);
// }
if (!isValidEmail(et_code.getText())) {
// edittext2.setError("Email is invalid");
et_code.setError("Email is invalid");
textinputlayout_code.setError("邮箱格式错误");
textinputlayout_code.setErrorEnabled(true);
} else {
textinputlayout_code.setError(null);
textinputlayout_code.setErrorEnabled(false);
}
//邮箱输入框清空后,颜色恢复默认
if (TextUtils.isEmpty(et_code.getText().toString().trim())) {
textinputlayout_code.setErrorEnabled(false);
}
if (charSequence.toString().length() < 1) {
textinputlayout_code.setErrorEnabled(false);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
et_code.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
if (!isValidEmail(et_code.getText())) {
// et_email.setError("Email is invalid");
// textInputLayout2.setError("Email is invalid");
} else {
// textInputLayout2.setError(null);
}
}
}
});
}
public static boolean isValidEmail(CharSequence target) {
return !TextUtils.isEmpty(target) && android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();
}
// 介绍:
// app:counterEnabled="true" //设置为true才能显字符数
// app:counterMaxLength="5" //设置最大字符数为5
// app:counterOverflowTextAppearance="@style/HintError" //设置超出字符数后提示文字的颜色,如果不设置默认为@color/colorAccent的颜色
// android:layout_height="wrap_content">
}
四.登录样式4:
1.主函数代码:
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Intent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import com.hjq.demo.R;
import com.hjq.demo.common.MyActivity;
import com.hjq.demo.helper.InputTextHelper;
import com.hjq.demo.other.IntentKey;
import com.hjq.demo.other.KeyboardWatcher;
import com.hjq.demo.wxapi.WXEntryActivity;
import com.hjq.image.ImageLoader;
import com.hjq.umeng.Platform;
import com.hjq.umeng.UmengClient;
import com.hjq.umeng.UmengLogin;
import butterknife.BindView;
import butterknife.OnClick;
/**
* 登录界面
*/
public final class LoginActivity extends MyActivity
implements UmengLogin.OnLoginListener,
KeyboardWatcher.SoftKeyboardStateListener {
@BindView(R.id.iv_login_logo)
ImageView mLogoView;
@BindView(R.id.ll_login_body)
LinearLayout mBodyLayout;
@BindView(R.id.et_login_phone)
EditText mPhoneView;
@BindView(R.id.et_login_password)
EditText mPasswordView;
@BindView(R.id.btn_login_commit)
Button mCommitView;
@BindView(R.id.v_login_blank)
View mBlankView;
@BindView(R.id.ll_login_other)
View mOtherView;
@BindView(R.id.iv_login_qq)
View mQQView;
@BindView(R.id.iv_login_wx)
View mWeChatView;
/** logo 缩放比例 */
private final float mLogoScale = 0.8f;
/** 动画时间 */
private final int mAnimTime = 300;
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
@Override
protected void initView() {
InputTextHelper.with(this)
.addView(mPhoneView)
.addView(mPasswordView)
.setMain(mCommitView)
.setListener(new InputTextHelper.OnInputTextListener() {
@Override
public boolean onInputChange(InputTextHelper helper) {
return mPhoneView.getText().toString().length() == 11 &&
mPasswordView.getText().toString().length() >= 6;
}
})
.build();
post(new Runnable() {
@Override
public void run() {
// 因为在小屏幕手机上面,因为计算规则的因素会导致动画效果特别夸张,所以不在小屏幕手机上面展示这个动画效果
if (mBlankView.getHeight() > mBodyLayout.getHeight()) {
// 只有空白区域的高度大于登录框区域的高度才展示动画
KeyboardWatcher.with(LoginActivity.this)
.setListener(LoginActivity.this);
}
}
});
}
@Override
protected void initData() {
// 判断用户当前有没有安装 QQ
if (!UmengClient.isAppInstalled(this, Platform.QQ)) {
mQQView.setVisibility(View.GONE);
}
// 判断用户当前有没有安装微信
if (!UmengClient.isAppInstalled(this, Platform.WECHAT)) {
mWeChatView.setVisibility(View.GONE);
}
// 如果这两个都没有安装就隐藏提示
if (mQQView.getVisibility() == View.GONE && mWeChatView.getVisibility() == View.GONE) {
mOtherView.setVisibility(View.GONE);
}
}
@Override
public void onRightClick(View v) {
// 跳转到注册界面
startActivityForResult(RegisterActivity.class, new ActivityCallback() {
@Override
public void onActivityResult(int resultCode, @Nullable Intent data) {
// 如果已经注册成功,就执行登录操作
if (resultCode == RESULT_OK && data != null) {
mPhoneView.setText(data.getStringExtra(IntentKey.PHONE));
mPasswordView.setText(data.getStringExtra(IntentKey.PASSWORD));
onClick(mCommitView);
}
}
});
}
@OnClick({R.id.tv_login_forget, R.id.btn_login_commit, R.id.iv_login_qq, R.id.iv_login_wx})
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_login_forget:
startActivity(PasswordForgetActivity.class);
break;
case R.id.btn_login_commit:
if (mPhoneView.getText().toString().length() != 11) {
toast(R.string.common_phone_input_error);
} else {
showLoading();
postDelayed(new Runnable() {
@Override
public void run() {
showComplete();
// 处理登录
startActivityFinish(HomeActivity.class);
}
}, 2000);
}
break;
case R.id.iv_login_qq:
case R.id.iv_login_wx:
toast("记得改好第三方 AppID 和 AppKey,否则会调不起来哦");
Platform platform;
switch (v.getId()) {
case R.id.iv_login_qq:
platform = Platform.QQ;
break;
case R.id.iv_login_wx:
platform = Platform.WECHAT;
toast("也别忘了改微信 " + WXEntryActivity.class.getSimpleName() + " 类所在的包名哦");
break;
default:
throw new IllegalStateException("are you ok?");
}
UmengClient.login(this, platform, this);
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 友盟登录回调
UmengClient.onActivityResult(this, requestCode, resultCode, data);
}
/**
* 友盟第三方登录授权回调接口
* {@link UmengLogin.OnLoginListener}
*/
/**
* 授权成功的回调
*
* @param platform 平台名称
* @param data 用户资料返回
*/
@Override
public void onSucceed(Platform platform, UmengLogin.LoginData data) {
// 判断第三方登录的平台
switch (platform) {
case QQ:
break;
case WECHAT:
break;
default:
break;
}
ImageLoader.with(this)
.load(data.getIcon())
.circle()
.into(mLogoView);
toast("昵称:" + data.getName() + "\n" + "性别:" + data.getSex());
toast("id:" + data.getId());
toast("token:" + data.getToken());
}
/**
* 授权失败的回调
*
* @param platform 平台名称
* @param t 错误原因
*/
@Override
public void onError(Platform platform, Throwable t) {
toast("第三方登录出错:" + t.getMessage());
}
/**
* 授权取消的回调
*
* @param platform 平台名称
*/
@Override
public void onCancel(Platform platform) {
toast("取消第三方登录");
}
/**
* {@link KeyboardWatcher.SoftKeyboardStateListener}
*/
@Override
public void onSoftKeyboardOpened(int keyboardHeight) {
int screenHeight = getResources().getDisplayMetrics().heightPixels;
int[] location = new int[2];
// 获取这个 View 在屏幕中的坐标(左上角)
mBodyLayout.getLocationOnScreen(location);
//int x = location[0];
int y = location[1];
int bottom = screenHeight - (y + mBodyLayout.getHeight());
if (keyboardHeight > bottom){
// 执行位移动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mBodyLayout, "translationY", 0, -(keyboardHeight - bottom));
objectAnimator.setDuration(mAnimTime);
objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
objectAnimator.start();
// 执行缩小动画
mLogoView.setPivotX(mLogoView.getWidth() / 2f);
mLogoView.setPivotY(mLogoView.getHeight());
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mLogoView, "scaleX", 1.0f, mLogoScale);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(mLogoView, "scaleY", 1.0f, mLogoScale);
ObjectAnimator translationY = ObjectAnimator.ofFloat(mLogoView, "translationY", 0.0f, -(keyboardHeight - bottom));
animatorSet.play(translationY).with(scaleX).with(scaleY);
animatorSet.setDuration(mAnimTime);
animatorSet.start();
}
}
@Override
public void onSoftKeyboardClosed() {
// 执行位移动画
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mBodyLayout, "translationY", mBodyLayout.getTranslationY(), 0);
objectAnimator.setDuration(mAnimTime);
objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
objectAnimator.start();
if (mLogoView.getTranslationY() == 0){
return;
}
// 执行放大动画
mLogoView.setPivotX(mLogoView.getWidth() / 2f);
mLogoView.setPivotY(mLogoView.getHeight());
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mLogoView, "scaleX", mLogoScale, 1.0f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(mLogoView, "scaleY", mLogoScale, 1.0f);
ObjectAnimator translationY = ObjectAnimator.ofFloat(mLogoView, "translationY", mLogoView.getTranslationY(), 0);
animatorSet.play(translationY).with(scaleX).with(scaleY);
animatorSet.setDuration(mAnimTime);
animatorSet.start();
}
}
package com.hjq.demo.other;
import android.app.Activity;
import android.app.Application;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
/**
软键盘监听类
*/
public final class KeyboardWatcher implements
ViewTreeObserver.OnGlobalLayoutListener,
Application.ActivityLifecycleCallbacks {
private Activity mActivity;
private View mContentView;
private SoftKeyboardStateListener mListeners;
private boolean isSoftKeyboardOpened;
private int mStatusBarHeight;
public static KeyboardWatcher with(Activity activity) {
return new KeyboardWatcher(activity);
}
private KeyboardWatcher(Activity activity) {
mActivity = activity;
mContentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
mActivity.getApplication().registerActivityLifecycleCallbacks(this);
mContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
// 获取 status_bar_height 资源的 ID
int resourceId = mActivity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
//根据资源 ID 获取响应的尺寸值
mStatusBarHeight = mActivity.getResources().getDimensionPixelSize(resourceId);
}
}
/**
* {@link ViewTreeObserver.OnGlobalLayoutListener}
*/
@Override
public void onGlobalLayout() {
final Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
mContentView.getWindowVisibleDisplayFrame(r);
final int heightDiff = mContentView.getRootView().getHeight() - (r.bottom - r.top);
if (!isSoftKeyboardOpened && heightDiff > mContentView.getRootView().getHeight() / 4) {
isSoftKeyboardOpened = true;
if ((mActivity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != WindowManager.LayoutParams.FLAG_FULLSCREEN) {
if (mListeners != null) {
mListeners.onSoftKeyboardOpened(heightDiff - mStatusBarHeight);
}
} else {
if (mListeners != null) {
mListeners.onSoftKeyboardOpened(heightDiff);
}
}
} else if (isSoftKeyboardOpened && heightDiff < mContentView.getRootView().getHeight() / 4) {
isSoftKeyboardOpened = false;
if (mListeners != null) {
mListeners.onSoftKeyboardClosed();
}
}
}
/**
* 设置软键盘弹出监听
*/
public void setListener(SoftKeyboardStateListener listener) {
mListeners = listener;
}
/**
* {@link Application.ActivityLifecycleCallbacks}
*/
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (mActivity == activity) {
mActivity.getApplication().unregisterActivityLifecycleCallbacks(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mContentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
mActivity = null;
mContentView = null;
mListeners = null;
}
}
/**
* 软键盘状态监听器
*/
public interface SoftKeyboardStateListener {
/**
* 软键盘弹出了
* @param keyboardHeight 软键盘高度
*/
void onSoftKeyboardOpened(int keyboardHeight);
/**
* 软键盘收起了
*/
void onSoftKeyboardClosed();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@color/white"
android:gravity="center_horizontal"
android:layoutAnimation="@anim/layout_animation_from_bottom"
android:orientation="vertical"
tools:context=".ui.activity.LoginActivity"
tools:layoutAnimation="@null">
<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="50dp"
app:backButton="false"
app:barStyle="transparent"
app:rightColor="@color/colorAccent"
app:rightTitle="@string/login_register"
app:title="" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_login_logo"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:src="@drawable/ic_logo" />
<LinearLayout
android:id="@+id/ll_login_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.hjq.widget.view.ClearEditText
android:id="@+id/et_login_phone"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="10dp"
android:layout_marginRight="40dp"
android:hint="@string/common_phone_input_hint"
android:inputType="textVisiblePassword"
android:singleLine="true"
app:regexType="mobile" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp" />
<com.hjq.widget.view.PasswordEditText
android:id="@+id/et_login_password"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="20dp"
android:layout_marginRight="40dp"
android:hint="@string/common_password_input_error"
android:maxLength="20"
android:maxLines="1" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_login_forget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="40dp"
android:layout_marginTop="15dp"
android:layout_marginRight="60dp"
android:text="@string/login_forget"
android:textColor="@color/colorAccent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_login_commit"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="30dp"
android:layout_marginRight="40dp"
android:text="@string/login_text" />
</LinearLayout>
<View
android:id="@+id/v_login_blank"
android:layout_width="wrap_content"
android:layout_height="0px"
android:layout_weight="5" />
<LinearLayout
android:id="@+id/ll_login_other"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_vertical"
android:orientation="horizontal">
<View
style="@style/HorizontalLineStyle"
android:layout_width="60dp"
android:layout_weight="1" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:text="@string/login_other"
android:textColor="@color/black50" />
<View
style="@style/HorizontalLineStyle"
android:layout_width="60dp"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.hjq.widget.view.ScaleImageView
android:id="@+id/iv_login_qq"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginStart="30dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="25dp"
android:layout_weight="1"
android:src="@drawable/ic_login_qq"
app:scaleRatio="1.2" />
<com.hjq.widget.view.ScaleImageView
android:id="@+id/iv_login_wx"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginStart="30dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="25dp"
android:layout_weight="1"
android:src="@drawable/ic_login_wx"
app:scaleRatio="1.2" />
</LinearLayout>
</LinearLayout>
layout_animation_from_bottom.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_from_bottom"
android:animationOrder="normal"
android:delay="15%" />
<!-- 默认文本框样式 -->
<style name="EditTextStyle">
<item name="android:background">@null</item>
<item name="android:textSize">15sp</item>
<item name="android:textColorHint">#A4A4A4</item>
<item name="android:textColor">#333333</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:paddingLeft">10dp</item>
<item name="android:paddingRight">10dp</item>
</style>
<!-- 默认水平分割线样式 -->
<style name="HorizontalLineStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/line_size</item>
<item name="android:background">@color/colorLine</item>
</style>
<!-- 默认圆角按钮样式 -->
<style name="ButtonStyle" parent="Widget.AppCompat.Button.Borderless">
<item name="android:paddingLeft">15dp</item>
<item name="android:paddingRight">15dp</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/white90</item>
<item name="android:gravity">center</item>
<item name="android:background">@drawable/selector_button</item>
<item name="android:foreground">@null</item>
</style>
selector_button.xml
<?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="@dimen/button_round_size" />
<solid android:color="@color/colorButtonDisable" />
</shape>
</item>
<!-- 按压状态 -->
<item android:state_pressed="true">
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_round_size" />
<solid android:color="@color/colorButtonPressed" />
</shape>
</item>
<!-- 焦点状态 -->
<item android:state_focused="true">
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_round_size" />
<solid android:color="@color/colorButtonPressed" />
</shape>
</item>
<!-- 默认状态 -->
<item>
<shape android:shape="rectangle">
<corners android:radius="@dimen/button_round_size" />
<solid android:color="@color/colorAccent" />
</shape>
</item>
</selector>
五.登录之重置密码:
1.主函数代码:
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.hjq.demo.R;
import com.hjq.demo.common.MyActivity;
import com.hjq.demo.helper.InputTextHelper;
import butterknife.BindView;
import butterknife.OnClick;
/**
* 重置密码
*/
public final class PasswordResetActivity extends MyActivity {
@BindView(R.id.et_password_reset_password1)
EditText mPasswordView1;
@BindView(R.id.et_password_reset_password2)
EditText mPasswordView2;
@BindView(R.id.btn_password_reset_commit)
Button mCommitView;
@Override
protected int getLayoutId() {
return R.layout.activity_password_reset;
}
@Override
protected void initView() {
InputTextHelper.with(this)
.addView(mPasswordView1)
.addView(mPasswordView2)
.setMain(mCommitView)
.setListener(new InputTextHelper.OnInputTextListener() {
@Override
public boolean onInputChange(InputTextHelper helper) {
return mPasswordView1.getText().toString().length() >= 6 &&
mPasswordView1.getText().toString().equals(mPasswordView2.getText().toString());
}
})
.build();
}
@Override
protected void initData() {
}
@OnClick({R.id.btn_password_reset_commit})
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_password_reset_commit:
toast(R.string.password_reset_success);
finish();
break;
default:
break;
}
}
}
2.布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".ui.activity.PasswordResetActivity">
<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/password_reset_title" />
<com.hjq.widget.view.PasswordEditText
android:id="@+id/et_password_reset_password1"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:background="@color/white"
android:drawableLeft="@drawable/ic_small_safe"
android:drawablePadding="15dp"
android:hint="@string/password_reset_phone_hint1"
android:inputType="textPassword"
android:maxLength="20"
android:maxLines="1"
android:paddingLeft="20dp"
android:paddingTop="18dp"
android:paddingRight="20dp"
android:paddingBottom="18dp" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp" />
<com.hjq.widget.view.PasswordEditText
android:id="@+id/et_password_reset_password2"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:drawableLeft="@drawable/ic_small_safe"
android:drawablePadding="15dp"
android:hint="@string/password_reset_phone_hint2"
android:maxLength="20"
android:maxLines="1"
android:paddingLeft="20dp"
android:paddingTop="18dp"
android:paddingRight="20dp"
android:paddingBottom="18dp" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_password_reset_commit"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="40dp"
android:layout_marginRight="40dp"
android:text="@string/common_step_complete" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@color/white"
android:orientation="vertical"
tools:context=".ui.activity.RegisterActivity">
<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="50dp"
app:backButton="false"
app:barStyle="transparent"
app:leftColor="@color/colorAccent"
app:leftTitle="@string/register_login"
app:title="" />
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:gravity="center_horizontal"
android:layoutAnimation="@anim/layout_animation_fall_down"
android:orientation="vertical"
tools:layoutAnimation="@null">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/register_title"
android:textColor="@color/black60"
android:textSize="23sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/register_hint"
android:textColor="@color/black20"
android:textSize="14sp" />
<LinearLayout
android:id="@+id/ll_register_edit1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<FrameLayout
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1">
<com.hjq.widget.view.RegexEditText
android:id="@+id/et_register_phone"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/common_phone_input_hint"
android:inputType="textVisiblePassword"
android:maxLines="1"
android:singleLine="true"
app:regexType="mobile" />
<View
style="@style/HorizontalLineStyle"
android:layout_gravity="bottom" />
</FrameLayout>
<com.hjq.widget.view.CountdownView
android:id="@+id/cv_register_countdown"
style="@style/CountdownViewStyle" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_register_code"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="@string/common_code_input_hint"
android:inputType="number"
android:maxLength="4"
android:maxLines="1"
android:singleLine="true" />
<View style="@style/HorizontalLineStyle" />
<com.hjq.widget.view.PasswordEditText
android:id="@+id/et_register_password1"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="@string/register_password_hint1"
android:maxLength="20"
android:maxLines="1" />
<View style="@style/HorizontalLineStyle" />
<com.hjq.widget.view.PasswordEditText
android:id="@+id/et_register_password2"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:hint="@string/register_password_hint2"
android:maxLength="20"
android:maxLines="1" />
<View style="@style/HorizontalLineStyle" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_register_commit"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginBottom="20dp"
android:text="@string/register_title" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".ui.activity.PasswordForgetActivity">
<com.hjq.bar.TitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/password_forget_title" />
<com.hjq.widget.view.RegexEditText
android:id="@+id/et_password_forget_phone"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:background="@color/white"
android:drawableLeft="@drawable/ic_small_phone"
android:drawablePadding="15dp"
android:hint="@string/common_phone_input_hint"
android:inputType="textVisiblePassword"
android:paddingLeft="20dp"
android:paddingTop="18dp"
android:paddingRight="20dp"
android:paddingBottom="18dp"
android:singleLine="true"
app:regexType="mobile" />
<View
style="@style/HorizontalLineStyle"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_password_forget_code"
style="@style/EditTextStyle"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@color/white"
android:drawableLeft="@drawable/ic_small_safe"
android:drawablePadding="15dp"
android:hint="@string/common_code_input_hint"
android:paddingLeft="20dp"
android:paddingTop="18dp"
android:paddingRight="20dp"
android:paddingBottom="18dp"
android:singleLine="true" />
<com.hjq.widget.view.CountdownView
android:id="@+id/cv_password_forget_countdown"
style="@style/CountdownViewStyle" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_password_forget_commit"
style="@style/ButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="50dp"
android:layout_marginRight="40dp"
android:text="@string/common_step_next" />
</LinearLayout>
https://github.com/qingmei2/Samples-Android
请忽略下面的笔记:
/**
* 自定义绚丽的ProgressBar.
*/
public class ProgressBarView1 extends View {
/**
* 进度条所占用的角度
*/
private static final int ARC_FULL_DEGREE = 300;
/**
* 弧线的宽度
*/
private int STROKE_WIDTH;
/**
* 组件的宽,高
*/
private int width, height;
/**
* 进度条最大值和当前进度值
*/
private float max, progress;
/**
* 是否允许拖动进度条
*/
private boolean draggingEnabled = false;
/**
* 绘制弧线的矩形区域
*/
private RectF circleRectF;
/**
* 绘制弧线的画笔
*/
private Paint progressPaint;
/**
* 绘制文字的画笔
*/
private Paint textPaint;
/**
* 绘制当前进度值的画笔
*/
private Paint thumbPaint;
/**
* 圆弧的半径
*/
private int circleRadius;
/**
* 圆弧圆心位置
*/
private int centerX, centerY;
public ProgressBarView1(Context context) {
super(context);
init();
}
public ProgressBarView1(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ProgressBarView1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
progressPaint = new Paint();
progressPaint.setAntiAlias(true);
textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setAntiAlias(true);
thumbPaint = new Paint();
thumbPaint.setAntiAlias(true);
//使用自定义字体
textPaint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fangz.ttf"));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (width == 0 || height == 0) {
width = getWidth();
height = getHeight();
//计算圆弧半径和圆心点
circleRadius = Math.min(width, height) / 2;
STROKE_WIDTH = circleRadius / 12;
circleRadius -= STROKE_WIDTH;
centerX = width / 2;
centerY = height / 2;
//圆弧所在矩形区域
circleRectF = new RectF();
circleRectF.left = centerX - circleRadius;
circleRectF.top = centerY - circleRadius;
circleRectF.right = centerX + circleRadius;
circleRectF.bottom = centerY + circleRadius;
}
}
private Rect textBounds = new Rect();
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float start = 90 + ((360 - ARC_FULL_DEGREE) >> 1); //进度条起始点
float sweep1 = ARC_FULL_DEGREE * (progress / max); //进度划过的角度
float sweep2 = ARC_FULL_DEGREE - sweep1; //剩余的角度
//绘制起始位置小圆形
progressPaint.setColor(Color.WHITE);
progressPaint.setStrokeWidth(0);
progressPaint.setStyle(Paint.Style.FILL);
float radians = (float) (((360.0f - ARC_FULL_DEGREE) / 2) / 180 * Math.PI);
float startX = centerX - circleRadius * (float) Math.sin(radians);
float startY = centerY + circleRadius * (float) Math.cos(radians);
canvas.drawCircle(startX, startY, STROKE_WIDTH / 2, progressPaint);
//绘制进度条
progressPaint.setStrokeWidth(STROKE_WIDTH);
progressPaint.setStyle(Paint.Style.STROKE);//设置空心
canvas.drawArc(circleRectF, start, sweep1, false, progressPaint);
//绘制进度条背景
progressPaint.setColor(Color.parseColor("#d64444"));
canvas.drawArc(circleRectF, start + sweep1, sweep2, false, progressPaint);
//绘制结束位置小圆形
progressPaint.setStrokeWidth(0);
progressPaint.setStyle(Paint.Style.FILL);
float endX = centerX + circleRadius * (float) Math.sin(radians);
float endY = centerY + circleRadius * (float) Math.cos(radians);
canvas.drawCircle(endX, endY, STROKE_WIDTH / 2, progressPaint);
//上一行文字
textPaint.setTextSize(circleRadius >> 1);
String text = (int) (100 * progress / max) + "";
float textLen = textPaint.measureText(text);
//计算文字高度
textPaint.getTextBounds("8", 0, 1, textBounds);
float h1 = textBounds.height();
//% 前面的数字水平居中,适当调整
float extra = text.startsWith("1") ? -textPaint.measureText("1") / 2 : 0;
canvas.drawText(text, centerX - textLen / 2 + extra, centerY - 30 + h1 / 2, textPaint);
//百分号
textPaint.setTextSize(circleRadius >> 2);
canvas.drawText("%", centerX + textLen / 2 + extra + 5, centerY - 30 + h1 / 2, textPaint);
//下一行文字
textPaint.setTextSize(circleRadius / 5);
text = "可用内存充足";
textLen = textPaint.measureText(text);
textPaint.getTextBounds(text, 0, text.length(), textBounds);
float h2 = textBounds.height();
canvas.drawText(text, centerX - textLen / 2, centerY + h1 / 2 + h2, textPaint);
//绘制进度位置,也可以直接替换成一张图片
float progressRadians = (float) (((360.0f - ARC_FULL_DEGREE) / 2 + sweep1) / 180 * Math.PI);
float thumbX = centerX - circleRadius * (float) Math.sin(progressRadians);
float thumbY = centerY + circleRadius * (float) Math.cos(progressRadians);
thumbPaint.setColor(Color.parseColor("#33d64444"));
canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 2.0f, thumbPaint);
thumbPaint.setColor(Color.parseColor("#99d64444"));
canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 1.4f, thumbPaint);
thumbPaint.setColor(Color.WHITE);
canvas.drawCircle(thumbX, thumbY, STROKE_WIDTH * 0.8f, thumbPaint);
}
private boolean isDragging = false;
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
if (!draggingEnabled) {
return super.onTouchEvent(event);
}
//处理拖动事件
float currentX = event.getX();
float currentY = event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//判断是否在进度条thumb位置
if (checkOnArc(currentX, currentY)) {
float newProgress = calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max;
setProgressSync(newProgress);
isDragging = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (isDragging) {
//判断拖动时是否移出去了
if (checkOnArc(currentX, currentY)) {
setProgressSync(calDegreeByPosition(currentX, currentY) / ARC_FULL_DEGREE * max);
} else {
isDragging = false;
}
}
break;
case MotionEvent.ACTION_UP:
isDragging = false;
break;
}
return true;
}
private float calDistance(float x1, float y1, float x2, float y2) {
return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
/**
* 判断该点是否在弧线上(附近)
*/
private boolean checkOnArc(float currentX, float currentY) {
float distance = calDistance(currentX, currentY, centerX, centerY);
float degree = calDegreeByPosition(currentX, currentY);
return distance > circleRadius - STROKE_WIDTH * 5 && distance < circleRadius + STROKE_WIDTH * 5
&& (degree >= -8 && degree <= ARC_FULL_DEGREE + 8);
}
/**
* 根据当前位置,计算出进度条已经转过的角度。
*/
private float calDegreeByPosition(float currentX, float currentY) {
float a1 = (float) (Math.atan(1.0f * (centerX - currentX) / (currentY - centerY)) / Math.PI * 180);
if (currentY < centerY) {
a1 += 180;
} else if (currentY > centerY && currentX > centerX) {
a1 += 360;
}
return a1 - (360 - ARC_FULL_DEGREE) / 2;
}
public void setMax(int max) {
this.max = max;
invalidate();
}
public void setProgress(float progress) {
final float validProgress = checkProgress(progress);
//动画切换进度值
new Thread(new Runnable() {
@Override
public void run() {
float oldProgress = ProgressBarView1.this.progress;
for (int i = 1; i <= 100; i++) {
ProgressBarView1.this.progress = oldProgress + (validProgress - oldProgress) * (1.0f * i / 100);
postInvalidate();
SystemClock.sleep(20);
}
}
}).start();
}
public void setProgressSync(float progress) {
this.progress = checkProgress(progress);
invalidate();
}
//保证progress的值位于[0,max]
private float checkProgress(float progress) {
if (progress < 0) {
return 0;
}
return progress > max ? max : progress;
}
public void setDraggingEnabled(boolean draggingEnabled) {
this.draggingEnabled = draggingEnabled;
}
}