每一个人都会喜欢漂亮的登陆界面,一个App 给人们的第一印象是很是重要的。html
这篇文章将教你使用谷歌材料设计规范(Material design spec )和谷歌的新的设计支持库( design support library)来建立一个炫酷的登陆和注册界面。设计支持库实现了材料设计规范的一部分,它包含了一部分炫酷的UI 部件,让你的Android 应用给人一种优雅的感受。java
对事物的设计和布局方面,如何作到让人感受到屏幕上的内容是赏心悦目的,这里是咱们要权衡的重点,咱们会在顶部状态栏添加精细的触摸事件,并使用设计支持库的floating labels (实现自TextInputLayout)。android
几乎全部的事情都都已经照顾到你。git
完整的代码和样例托管在Githubgithub
当接口锁定时,防止后退按钮显示在登陆Activity 上。微信
自定义 ProgressDialog
来显示加载的状态。app
符合材料设计规范。ide
悬浮标签(floating labels)(来自设计支持库)布局
用户表单输入校验post
自定义状态栏样式
在每个Activity 测试模仿验证的方法。
剩下的就是实现本身的身份验证逻辑。
让咱们来设置登陆Activity,一般是开始你的应用程序,会显示给用户的第一个要启动的Activity。
若是你想要添加社交登陆按钮,请继续,可是当前在这个文章范围内,只给你基本的代码,让你有一个坚固的起点去构建你的验证流程。
须要注意的是 onBackPressed
方法将会被重写,这样将会防止用户关闭登陆Activity。
package com.sourcey.materiallogindemo; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.content.Intent; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import butterknife.ButterKnife; import butterknife.InjectView; public class LoginActivity extends AppCompatActivity { private static final String TAG = "LoginActivity"; private static final int REQUEST_SIGNUP = 0; @Bind(R.id.input_email) EditText _emailText; @Bind(R.id.input_password) EditText _passwordText; @Bind(R.id.btn_login) Button _loginButton; @Bind(R.id.link_signup) TextView _signupLink; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); ButterKnife.inject(this); _loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { login(); } }); _signupLink.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Start the Signup activity Intent intent = new Intent(getApplicationContext(), SignupActivity.class); startActivityForResult(intent, REQUEST_SIGNUP); } }); } public void login() { Log.d(TAG, "Login"); if (!validate()) { onLoginFailed(); return; } _loginButton.setEnabled(false); final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog); progressDialog.setIndeterminate(true); progressDialog.setMessage("Authenticating..."); progressDialog.show(); String email = _emailText.getText().toString(); String password = _passwordText.getText().toString(); // TODO: Implement your own authentication logic here. new android.os.Handler().postDelayed( new Runnable() { public void run() { // On complete call either onLoginSuccess or onLoginFailed onLoginSuccess(); // onLoginFailed(); progressDialog.dismiss(); } }, 3000); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_SIGNUP) { if (resultCode == RESULT_OK) { // TODO: Implement successful signup logic here // By default we just finish the Activity and log them in automatically this.finish(); } } } @Override public void onBackPressed() { // disable going back to the MainActivity moveTaskToBack(true); } public void onLoginSuccess() { _loginButton.setEnabled(true); finish(); } public void onLoginFailed() { Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show(); _loginButton.setEnabled(true); } public boolean validate() { boolean valid = true; String email = _emailText.getText().toString(); String password = _passwordText.getText().toString(); if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { _emailText.setError("enter a valid email address"); valid = false; } else { _emailText.setError(null); } if (password.isEmpty() || password.length() < 4 || password.length() > 10) { _passwordText.setError("between 4 and 10 alphanumeric characters"); valid = false; } else { _passwordText.setError(null); } return valid; } }
<img src="http://sourcey.com/beautiful-android-logn-and-signup-screens-with-material-design/screenshot-login.png" width="360" height="640" />
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fitsSystemWindows="true"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="56dp" android:paddingLeft="24dp" android:paddingRight="24dp"> <ImageView android:src="@drawable/logo" android:layout_width="wrap_content" android:layout_height="72dp" android:layout_marginBottom="24dp" android:layout_gravity="center_horizontal" /> <!-- Email Label --> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> <EditText android:id="@+id/input_email" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:hint="Email" /> </android.support.design.widget.TextInputLayout> <!-- Password Label --> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> <EditText android:id="@+id/input_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="Password"/> </android.support.design.widget.TextInputLayout> <android.support.v7.widget.AppCompatButton android:id="@+id/btn_login" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:layout_marginBottom="24dp" android:padding="12dp" android:text="Login"/> <TextView android:id="@+id/link_signup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp" android:text="No account yet? Create one" android:gravity="center" android:textSize="16dip"/> </LinearLayout> </ScrollView>
注册Activity 可让你在App 中建立一个用户,一般会在登陆Activity 中显示(注册的)连接。
<img src="http://sourcey.com/beautiful-android-logn-and-signup-screens-with-material-design/screenshot-signup.png" width="360" height="640" />
须要注意的是当用户注册成功时咱们会设置一个RESULT_OK
的结果值,这个结果将会在登陆Activity 中的 onActivityResult
方法中调用,而且肯定注册成功是如何处理的。当前逻辑是很简单的,当用户注册成功时咱们会立刻作一个记录。固然你想要实现邮箱验证,你须要本身来实现。
package com.sourcey.materiallogindemo; import android.app.ProgressDialog; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import butterknife.ButterKnife; import butterknife.InjectView; public class SignupActivity extends AppCompatActivity { private static final String TAG = "SignupActivity"; @Bind(R.id.input_name) EditText _nameText; @Bind(R.id.input_email) EditText _emailText; @Bind(R.id.input_password) EditText _passwordText; @Bind(R.id.btn_signup) Button _signupButton; @Bind(R.id.link_login) TextView _loginLink; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_signup); ButterKnife.inject(this); _signupButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { signup(); } }); _loginLink.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Finish the registration screen and return to the Login activity finish(); } }); } public void signup() { Log.d(TAG, "Signup"); if (!validate()) { onSignupFailed(); return; } _signupButton.setEnabled(false); final ProgressDialog progressDialog = new ProgressDialog(SignupActivity.this, R.style.AppTheme_Dark_Dialog); progressDialog.setIndeterminate(true); progressDialog.setMessage("Creating Account..."); progressDialog.show(); String name = _nameText.getText().toString(); String email = _emailText.getText().toString(); String password = _passwordText.getText().toString(); // TODO: Implement your own signup logic here. new android.os.Handler().postDelayed( new Runnable() { public void run() { // On complete call either onSignupSuccess or onSignupFailed // depending on success onSignupSuccess(); // onSignupFailed(); progressDialog.dismiss(); } }, 3000); } public void onSignupSuccess() { _signupButton.setEnabled(true); setResult(RESULT_OK, null); finish(); } public void onSignupFailed() { Toast.makeText(getBaseContext(), "Login failed", Toast.LENGTH_LONG).show(); _signupButton.setEnabled(true); } public boolean validate() { boolean valid = true; String name = _nameText.getText().toString(); String email = _emailText.getText().toString(); String password = _passwordText.getText().toString(); if (name.isEmpty() || name.length() < 3) { _nameText.setError("at least 3 characters"); valid = false; } else { _nameText.setError(null); } if (email.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches()) { _emailText.setError("enter a valid email address"); valid = false; } else { _emailText.setError(null); } if (password.isEmpty() || password.length() < 4 || password.length() > 10) { _passwordText.setError("between 4 and 10 alphanumeric characters"); valid = false; } else { _passwordText.setError(null); } return valid; } }
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fitsSystemWindows="true"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="56dp" android:paddingLeft="24dp" android:paddingRight="24dp"> <ImageView android:src="@drawable/logo" android:layout_width="wrap_content" android:layout_height="72dp" android:layout_marginBottom="24dp" android:layout_gravity="center_horizontal" /> <!-- Name Label --> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> <EditText android:id="@+id/input_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textCapWords" android:hint="Name" /> </android.support.design.widget.TextInputLayout> <!-- Email Label --> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> <EditText android:id="@+id/input_email" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:hint="Email" /> </android.support.design.widget.TextInputLayout> <!-- Password Label --> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp"> <EditText android:id="@+id/input_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:hint="Password"/> </android.support.design.widget.TextInputLayout> <!-- Signup Button --> <android.support.v7.widget.AppCompatButton android:id="@+id/btn_signup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:layout_marginBottom="24dp" android:padding="12dp" android:text="Create Account"/> <TextView android:id="@+id/link_login" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="24dp" android:text="Already a member? Login" android:gravity="center" android:textSize="16dip"/> </LinearLayout> </ScrollView>
为了让程序一切正常工做,咱们在须要在 app
目录下的 build.gradle
中添加一些依赖,ButterKnife
是可选的,固然咱们更喜欢用它让咱们的Java 代码更加整洁一些。
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.android.support:design:22.2.0' compile 'com.jakewharton:butterknife:7.0.1' }
还有一个咱们必需要在AndroidManifest
中添加声明Activity。我已经把AndroidManifest
清晰完整的代码贴了出来。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sourcey.materiallogindemo" > <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".LoginActivity" android:theme="@style/AppTheme.Dark" /> <activity android:name=".SignupActivity" android:theme="@style/AppTheme.Dark" /> </application> </manifest>
但愿这篇文章对你是有帮助的,若是这篇文章真的节约你宝贵的开发时间,请给我留言。
本文做者:sourcey
本文译者:Tikitoo
原文连接:http://sourcey.com/beautiful-android-login-and-signup-screens-with-material-design/
翻译连接:http://tikitoo.github.io/2016/05/17/beautiful-android-login-and-signup-screens-with-material-design-zh/
非商业转载转载请在开头注明做者详细信息
和本文出处
,以及本文全部内容。本文首发个人微信公众号,分享
Android 开发
和互联网内容
。
微信号:AndroidMate
公众号:安卓同窗