Diycode开源项目 LoginActivity分析

1.首先看一下效果

1.1.预览一下真实页面

  

  

1.2.分析一下:

    要求输入Email或者用户名,点击编辑框,弹出键盘,默认先进入输入Email或用户名编辑框。

    点击密码后,密码字样网上浮动一段距离,Email编辑框也是一样的,不过第一次默认是第一个。

    没有账号?点击注册后跳转到一个网页,采用手机默认浏览器跳转。

 


2.LoginActivity布局分析

2.1.首先看一下activity_login源代码

<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright 2017 GcsSloop
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~    http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  ~ Last modified 2017-03-19 01:27:22
  ~
  ~ GitHub:  https://github.com/GcsSloop
  ~ Website: http://www.gcssloop.com
  ~ Weibo:   http://weibo.com/GcsSloop
  -->
<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:id="@+id/activity_login"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.gcssloop.diycode.activity.LoginActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingLeft="14dp"
        android:paddingRight="14dp">
        <View
            android:id="@+id/span1"
            android:layout_width="0dp"
            android:layout_height="10dp"
            android:visibility="invisible"/>

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:scaleType="centerInside"
            android:src="@drawable/ic_logo"/>
        
        <View
            android:id="@+id/span2"
            android:layout_width="0dp"
            android:layout_height="80dp"
            android:visibility="invisible"/>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            >

            <EditText
                android:id="@+id/username"
                android:layout_width="match_parent"
                android:layout_height="36dp"
                android:layout_marginLeft="6dp"
                android:background="@null"
                android:hint="Email / 用户名"
                android:inputType="textEmailAddress|text"
                android:textSize="16sp"/>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_below="@id/username"
                android:layout_marginTop="2dp"
                android:background="@drawable/horizontal_line"/>

        </android.support.design.widget.TextInputLayout>

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            >

            <EditText
                android:id="@+id/password"
                android:layout_width="match_parent"
                android:layout_height="36dp"
                android:layout_marginLeft="6dp"
                android:background="@null"
                android:hint="密码"
                android:inputType="textPassword"
                android:textSize="16sp"/>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_below="@id/password"
                android:layout_marginTop="2dp"
                android:background="@drawable/horizontal_line"/>
        </android.support.design.widget.TextInputLayout>

        <View
            android:id="@+id/span3"
            android:layout_width="0dp"
            android:layout_height="20dp"
            android:visibility="invisible"/>

        <Button
            android:id="@+id/login"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_marginTop="6dp"
            android:background="@drawable/bg_longin_btn"
            android:text="登  录"
            android:textColor="@color/diy_white"
            android:textSize="18sp"/>

        <TextView
            android:layout_marginTop="20dp"
            android:padding="12dp"
            android:layout_gravity="center_horizontal"
            android:id="@+id/sign_up"
            android:text="没有账号?点击注册"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>
</LinearLayout>
View Code

  

2.2.代码和布局对应关系

  

 

2.3.从上之下分析布局

   最外层是一个LinearLayout==>一个线性布局,一般登录都是这样做的。

   然后是一个toolbar,自带返回按钮的标题栏。

   标题栏下面的布局也是一个线性布局,它将标题栏和下方登录界面分隔开了。

   下方的线性布局就很简单了。

   首先是一个view,就是一个最基本的视图,这里用作类似于占空间控件。

   有时候view可以当做一条分割线,这里讲将宽度设置为0,高度不等,巧妙利用了这个特点。

 

2.4.值得关注的是编辑框外层的一个TextInputLayout布局

  这里的编辑框布局都是外层的TextInputLayout,然后里面是一个EditText+View。

  

  TextInputLayout支持悬浮实现hint效果。给用户体验比较好。

  一个TextInputLayout只能包含一个EditText。

  参考文章:android新特性:TextInputLayout使用方法。


3.LoginActivity活动源代码分析

3.1.成员变量分析

  

  这里仅仅需要两个变量。一个是用户名的编辑框,一个是密码的编辑框。

 

3.2.实现两个在BaseActivity中定义的抽象方法

  

  首先确定登录活动的布局==>activity_login.xml

  然后将标题栏设空,获得用户名+密码的资源id

  最后将这两个资源id添加监听器。

 

3.3.实现登录接口,利用EventBus实现。 

  

  这个onLogin其实是只在点击了登录按钮后才执行。

  这里我思考了一下EventBus执行方式。

  首先在活动开始即onStart中注册EventBus.getDefault().register(this)即可。

  然后在活动的停止或者销毁中反注册EventBus.getDefault().unregister(this)即可。

  然后就是写一些只会在UI线程中执行的函数--要用@Subscribe(threadMode=ThreadMode.MAIN)定义。

 

  因为之前也碰到这种类似的方法,我还以为是多余,不会执行呢。

  没想到就是要执行的,只是换了一种方式。

 

  安装完Android Studio3.0之后,这个this前面也自动添加了subscriber字样。

  

  这里从SDK的API中获得了个人信息之后,直接finish,交给MainActivity来处理。

 

3.4.处理软键盘弹起

  

  在onStart中,就是默认点开之后,会弹出软键盘,用户即可输入用户名。

  

  注意点:获取当前布局的根布局用下面这种方法。

  

  如何理解ViewTreeObserver.OnGlobalLayoutListener?

  参考一下这篇文章:android利用OnGlobalLayoutListener获取视图高度。

  

  作用:当视图树中全局视图发生改变,配合View.GONE和View.INVISIBLE来实现布局上下移动。

      本例就是点击了第一个编辑框,整个布局会往上移动,不过这是利用视图的隐藏和显示完成的。

 

  具体的判断软键盘是否显示==>

  

  首先根布局已经获取,且已经作为一个参数了。

  这里如何获取根布局可视区域大小,这里采用了一个函数:

  rootView.getWindowVisibleDisplayFrame(存放到一个矩形)

  打印了一下:

  

  根布局获取到的getBottom:1857

  矩形获取到的getBottom:1920

  所以两者相减<软键盘高度,所有这里就没有弹出软键盘

 

  

  根布局获取到的getBottom:1857

  矩形获取到的getBottom:1285

  所以两者相减>软键盘高度,所有这里就弹出软键盘

 

3.5.处理点击事件

  

  这里我发现我上面写错了一点。

  就是处理登录接口的函数,就是点击登录之后,会执行这个API函数,而不是上面那个EventBus的onLogin。

  上面那个onLogin其实应该类似于回调效果吧。可能EventBus就是处理类似回调的东西吧。

 

  然后另外一个点击事件是注册,打开网页版才能注册,所以这里直接是打开一个链接。


4.总结一下

4.1.终于对EventBus有一定了解了。本篇文章一开始对于EventBus的了解是错误的,之后才发现EventBus就是用于

  SDK的API的函数回调效果,比如登录,首先去请求一个接口,API提供的login接口,然后后台通过Event来回调

  结果,之前我处理的都是网络请求,但是这个是采用Event事件的方式来回调,更加简单易懂。注意:有那个注

  解的地方@Subscribe(threadMode=ThreadMode.MAIN)的地方一定就是用了Event的地方,这里便是回调。

 

4.2.然后就是对于EventBus一定要先注册,一般在onStart中注册,然后反注册,一般在onStop或者onDestroy中反

  注册。

 

4.3.然后就是对于软键盘的弹起方式有了新的理解,这里采用view的invisible或者gone来实现,当然同时要确定

  什么时候invisible,什么时候gone,这里用了一个视图树来配合。如果视图树中某个视图发生改变,采用了

  addOnGlobalLayoutListener的方式复写了一个onGlobalLayout的方法来确定什么时候。

 

4.4.问题在于怎么确定软键盘是否弹起。这里也是采用了根布局rootView和Rect矩形和屏幕分辨率dm来配合,首先

  设软键盘高度为100,然后将根视图的可视区域存放到一个Rect中,然后根视图的bottom和矩形的bottom之差

  和软键盘高度的大小互相比较,以此为依据确定键盘是否弹出。

 

4.5.点击事件相对来说,更加容易一些,记得要判断String是否为空,这里直接用.isEmpty即可。然后注册采用了

  请求一个网址,用手机默认浏览器打开即进入相应页面。这个IntentUtil基本上每个项目都可以参考。

 

posted @ 2017-11-19 20:25  Jason_Jan  阅读(684)  评论(0编辑  收藏  举报