android最常见的UI之一,登录遍布各大APP,这么easy的东西还是要写写,主要是介绍下:密码的显示与隐藏,用户名和密码表单的网络请求和提交方式等细节问题。看一个简单的效果:
一,乾言
界面元素,logo,用户名,密码,登录按钮,底部两个按钮,访问有loading效果。
点击登录,获取用户和密码,简单校验,发送网络请求,然后校验请求结果,有异常做响应处理。
二,xml布局,view
布局代码,有点多,直接贴出来。需要的对应改吧改吧。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_gravity="center"
android:background="@drawable/login_bg">
<!--main content-->
<LinearLayout
android:id="@+id/ll_login_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_centerVertical="true"
android:orientation="vertical">
<!--logo-->
<ImageView
android:id="@+id/iv_logo"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="30dp"
android:src="@drawable/logo_oair" />
<!--login username-->
<LinearLayout
android:id="@+id/ll_login_user"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="@drawable/input_bg"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="20dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:background="@drawable/icon_user" />
<EditText
android:id="@+id/et_username"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="5"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:singleLine="true"
android:ellipsize="middle"
android:background="@android:color/transparent"
android:text="@string/login_username_default"
android:editable="false"
android:textColor="@color/white" />
<ImageView
android:id="@+id/iv_show_name"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="2dp"
android:scaleType="center"
android:clickable="true"
android:src="@drawable/icon_down" />
</LinearLayout>
<!--login password-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="@drawable/input_bg"
android:layout_gravity="center"
android:orientation="horizontal"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_marginTop="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:background="@drawable/icon_pwd"
/>
<EditText
android:id="@+id/et_password"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="5"
android:layout_gravity="center"
android:layout_marginLeft="15dp"
android:focusable="true"
android:inputType="textPassword"
android:background="@android:color/transparent"
android:textColor="@color/white" />
<ImageView
android:id="@+id/iv_hidden_pwd"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="2dp"
android:scaleType="center"
android:clickable="true"
android:src="@drawable/icon_hidden" />
</LinearLayout>
<!--login btn-->
<Button
android:id="@+id/btn_login"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_marginTop="40dp"
android:text="@string/login_btn"
android:textSize="20sp"
android:textColor="@drawable/text_select"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="@drawable/btn_login_bg" />
</LinearLayout>
<!--bottom btn-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:layout_below="@id/ll_login_body">
<TextView
android:id="@+id/tv_login_contactus"
android:text="@string/login_about"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:textSize="16sp"
android:padding="10dp"
android:clickable="true"
android:textColor="#FFF" />
<TextView
android:id="@+id/tv_login_guest"
android:text="@string/login_guest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:textSize="16sp"
android:padding="10dp"
android:clickable="true"
android:textColor="#FFF" />
</RelativeLayout>
<ProgressBar
android:id="@+id/pb_login"
style="@style/MyCircleProgressBar"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
android:indeterminateDuration="700"/>
</RelativeLayout>
注册view和事件
findViewById的事情就别自己一个个复制了,使用ButterKnife依赖注入view和事件,类似的框架很多。例如:
@Bind(R.id.et_username)
public EditText et_username;
@Bind(R.id.et_password)
public EditText et_password;
在onCreate方法中,注入:
ButterKnife.bind(this);
之前犯过错误,@Bind view需要使用public修饰属性。
Error:(68, 23) 错误: @Bind fields must not be private or static. (com.oair.oair_client.LoginActivity.iv_logo)
三,activity登录逻辑
获取edittext中的value,判断用户名,密码是否为空,如果ok就进行网络请求,post后台登录接口。我用retrofit+okhttp+RxJava/RxAndroid实现登录,json用内部封装的gson解析。
@OnClick(R.id.btn_login)
public void LoginOair(){
Login();
}
//Login 管理员登录
public void Login() {
// 点击登录的时候 拿到用户名和密码的值
username = et_username.getText().toString();
password = et_password.getText().toString();
//判断密码是否为空
if (StringUtils.isEmpty(password)) {
showDialog(context.getResources().getString(R.string.dialog_pwd_empty));
} else {
//验证登录是否成功
postLogin();
}
}
private void postLogin() {
pb_login.setVisibility(View.VISIBLE);
MyRetrofitUtils.init().loginOair(password, new Subscriber<OairResponse>() {
@Override
public void onCompleted() {
pb_login.setVisibility(View.GONE);
}
@Override
public void onError(Throwable e) {
checkLocalPwd();
LogUtils.debug(TAG,"error "+e.toString());
pb_login.setVisibility(View.GONE);
}
@Override
public void onNext(OairResponse oairResponse) {
LogUtils.debug(TAG,oairResponse.toString());
if (oairResponse.result == MyConstant.RESULT_SUCCESS){
enterMainActivity();
}else{ showDialog(context.getResources().getString(R.string.dialog_pwd_error));
}
}
});
}
不会用?可以使用你喜欢的网络访问方式,OKHTTP,HTTPUrlConnection,xUtils,volley都行。或者请看我的另外一篇文章,点击打开:
RxJava+Retrofit+Gson实现网络请求
四,隐藏和显示密码
EditText控件本身就封装好了显示与隐藏的方法,可以方便地将文本置为可见,或者隐藏。
//切换输入密码的模式,明文or密文显示
private boolean isHidden=true;
@OnClick(R.id.iv_hidden_pwd)
public void hiddenPassword() {
if (isHidden) {
//设置EditText文本为可见的
et_password.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
} else {
//设置EditText文本为隐藏的
et_password.setTransformationMethod(PasswordTransformationMethod.getInstance());
}
isHidden = !isHidden;
et_password.postInvalidate();
//切换后将EditText光标置于末尾
CharSequence charSequence = et_password.getText();
if (charSequence!=null) {
Spannable spanText = (Spannable) charSequence;
Selection.setSelection(spanText, charSequence.length());
}
}
五,输入法弹出,布局调整
有时候手机频幕小,弹出输入法框,可能会将edittext控件挡住,影响输入。这时候我们可以配置下activity。
<activity
android:name="com.xx.client.LoginActivity"
android:configChanges="keyboardHidden|orientation"
android:label="@string/title_activity_login"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
重点就是android:configChanges和android:windowSoftInputMode的属性,让activity自动调整界面,输入法位于输入框的下方。
六,总结
看似简单的一个功能,细看起来,知识点还是挺多的。这里面还有很多东西没有列出,比如用户名下拉选择一个用户登录,登录保存状态下次免登录,cookie的使用等。
未完待续,欢迎交流,杜乾,Dusan,Q 291902259。