仿QQ空间登录,解决软键盘弹出挡住输入框的问题

 我们在开发Android应用中,登录和注册界面是少不了的,往往在做登录注册的时候如果给界面加一个LOGO,就有可能把用户名和密码框放在手机屏幕的中间或底部,这样当软键盘弹出的时候,就有可能挡住输入框(往往用户输完用户名和密码还要按返回键盘才能登录),这样用户体验是不好的,我曾今也为这种事情很头疼。首先说一下我原来想到过的解决办法:
      一、原来想到过的解决办法:
    (1)、把登录和输入框让美工做在顶部,不要用LOGO图片类似于淘宝客户端(如下图):这样键盘弹出就不会影响到输入框,但是这样始终不是解决问题的方法(我原来常常让美工设计登录不要设计登录LOGO)

(2)、在布局根结点中加入ScrollView结点,这样当看不见输入框的时候手动滚一下就可以看到,这种方法也可行
(3)、自己给View做一个平移动画,然后处理键盘弹出和消失view的移动,这种设计比较麻烦,而且当View移动了以后要重新计算View的坐标位置,否则拿不到控件的监听事件(表面上看View是移动了,可是移动的只是图片,View上面控件的事件还在原来的位置,比较郁闷)。
(4)、重写RelativeLayout获取当前屏幕高度,实现onMesure、onSizeChanged方法来实现。废话不多说,我们今天采用第(4)种比较正规的方法来实现QQ空间登录页,先上图,无图无真相:以下分别是键盘没有弹出,和键盘弹出时登录情形(以下是我仿写的,布局用的就是QQ空间的布局)
   

二、实现代码(1)、重写RelatvieLayout(自定义View),实现onMesure、onSizeChanged方法。
  1. package com.jun.qqzomelogin;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.util.AttributeSet;
  5. import android.view.Display;
  6. import android.widget.RelativeLayout;
  7. /**
  8. * 自定义布局解决键盘弹出挡住输入框的问题
  9. */
  10. public class InputMethodRelativeLayout extends RelativeLayout {
  11.         private int width;
  12.         protected OnSizeChangedListenner onSizeChangedListenner;
  13.         private boolean sizeChanged  = false; //变化的标志
  14.         private int height;
  15.         private int screenWidth; //屏幕宽度
  16.         private int screenHeight; //屏幕高度
  17.         public InputMethodRelativeLayout(Context paramContext,
  18.                         AttributeSet paramAttributeSet) {
  19.                 super(paramContext, paramAttributeSet);
  20.                 Display localDisplay = ((Activity) paramContext).getWindowManager()
  21.                                 .getDefaultDisplay();
  22.                 this.screenWidth = localDisplay.getWidth() ;
  23.                 this.screenHeight = localDisplay.getHeight();
  24.         }
  25.         public InputMethodRelativeLayout(Context paramContext,
  26.                         AttributeSet paramAttributeSet, int paramInt) {
  27.                 super(paramContext, paramAttributeSet, paramInt);
  28.         }
  29.         @Override
  30.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  31.                 this.width = widthMeasureSpec;
  32.                 this.height = heightMeasureSpec;
  33.                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  34.         }
  35.         
  36.         @Override
  37.         public void onSizeChanged(int w, int h, int oldw,
  38.                         int oldh) {
  39.                 //监听不为空、宽度不变、当前高度与历史高度不为0 
  40.                 if ((this.onSizeChangedListenner!= null) && (w == oldw) && (oldw != 0)
  41.                                 && (oldh != 0)) {
  42.                         if ((h >= oldh)
  43.                                         || (Math.abs(h - oldh) <= 1 * this.screenHeight / 4)) {
  44.                                 if ((h <= oldh)
  45.                                                 || (Math.abs(h - oldh) <= 1 * this.screenHeight / 4))
  46.                                         return;
  47.                                 this.sizeChanged  = false;
  48.                         } else {
  49.                                 this.sizeChanged  = true;
  50.                         }
  51.                         this.onSizeChangedListenner.onSizeChange(this.sizeChanged ,oldh, h);
  52.                         measure(this.width - w + getWidth(), this.height
  53.                                         - h + getHeight());
  54.                 }
  55.         }
  56.         /**
  57.          * 设置监听事件
  58.          * @param paramonSizeChangedListenner
  59.          */
  60.         public void setOnSizeChangedListenner(
  61.                         InputMethodRelativeLayout.OnSizeChangedListenner paramonSizeChangedListenner) {
  62.                 this.onSizeChangedListenner = paramonSizeChangedListenner;
  63.         }
  64.  
  65.         //  大小改变的内部接口
  66.         public abstract interface OnSizeChangedListenner {
  67.                 public abstract void onSizeChange(boolean paramBoolean, int w,int h);
  68.         }
  69. }

然后把以上布局引入到自己的xml布局中。如QQ空间的登录布局

activity_main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <com.jun.qqzomelogin.InputMethodRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:id="@id/loginpage"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     android:background="@drawable/qz_bitmap_login" >
  7.     <LinearLayout
  8.         android:id="@id/login_container"
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         android:gravity="center"
  12.         android:orientation="vertical"
  13.         android:paddingLeft="15.0dip"
  14.         android:paddingRight="15.0dip" >
  15.                 <!-- 大logo -->
  16.         <LinearLayout
  17.             android:id="@id/login_logo_layout_v"
  18.             android:layout_width="wrap_content"
  19.             android:layout_height="wrap_content"
  20.             android:layout_marginBottom="34.0dip"
  21.             android:layout_marginTop="43.0dip"
  22.             android:orientation="vertical" >
  23.             <ImageView
  24.                 android:id="@id/login_logoimg"
  25.                 android:layout_width="125.0dip"
  26.                 android:layout_height="125.0dip"
  27.                 android:adjustViewBounds="true"
  28.                 android:gravity="center"
  29.                 android:src="@drawable/logo_login" />
  30.             <ImageView
  31.                 android:layout_width="125.0dip"
  32.                 android:layout_height="35.0dip"
  33.                 android:layout_marginTop="10.0dip"
  34.                 android:adjustViewBounds="true"
  35.                 android:gravity="center"
  36.                 android:src="@drawable/qz_icon_logo_word_login" />
  37.         </LinearLayout>
  38.                 <!-- 小LOGO -->
  39.         <LinearLayout
  40.             android:id="@id/login_logo_layout_h"
  41.             android:layout_width="fill_parent"
  42.             android:layout_height="wrap_content"
  43.             android:layout_marginBottom="11.0dip"
  44.             android:layout_marginTop="16.0dip"
  45.             android:gravity="left|center"
  46.             android:orientation="horizontal"
  47.             android:visibility="gone" >
  48.             <ImageView
  49.                 android:layout_width="42.0dip"
  50.                 android:layout_height="42.0dip"
  51.                 android:adjustViewBounds="true"
  52.                 android:gravity="center"
  53.                 android:src="@drawable/logo_login" />
  54.             <ImageView
  55.                 android:layout_width="93.0dip"
  56.                 android:layout_height="30.0dip"
  57.                 android:layout_marginLeft="5.0dip"
  58.                 android:adjustViewBounds="true"
  59.                 android:src="@drawable/qz_icon_logo_word_login" />
  60.         </LinearLayout>
  61.         <FrameLayout
  62.             android:layout_width="fill_parent"
  63.             android:layout_height="45.0dip" >
  64.             <EditText
  65.                 android:id="@id/qqId"
  66.                 android:layout_width="fill_parent"
  67.                 android:layout_height="fill_parent"
  68.                 android:background="@drawable/qz_bg_container_cell_top_normal"
  69.                 android:hint="QQ号/手机号/邮箱"
  70.                 android:inputType="textEmailAddress"
  71.                 android:maxLength="50"
  72.                 android:paddingLeft="15.0dip"
  73.                 android:paddingRight="80.0dip"
  74.                 android:singleLine="true"
  75.                 android:text=""
  76.                 android:textColor="#ff000000"
  77.                 android:textColorHint="#ffbbbbbb"
  78.                 android:textSize="16.0dip" />
  79.             <ImageView
  80.                 android:id="@id/uin_close"
  81.                 android:layout_width="30.0dip"
  82.                 android:layout_height="45.0dip"
  83.                 android:layout_gravity="right|center"
  84.                 android:layout_marginRight="40.0dip"
  85.                 android:background="@android:color/transparent"
  86.                 android:clickable="true"
  87.                 android:scaleType="center"
  88.                 android:src="@drawable/qz_icon_close"
  89.                 android:visibility="invisible" />
  90.             <ImageView
  91.                 android:id="@id/selectId"
  92.                 android:layout_width="40.0dip"
  93.                 android:layout_height="45.0dip"
  94.                 android:layout_gravity="right|center"
  95.                 android:background="@android:color/transparent"
  96.                 android:clickable="true"
  97.                 android:paddingLeft="5.0dip"
  98.                 android:paddingRight="15.0dip"
  99.                 android:scaleType="center"
  100.                 android:src="@drawable/qz_icon_navbar_drop_down" />
  101.         </FrameLayout>
  102.         <FrameLayout
  103.             android:layout_width="fill_parent"
  104.             android:layout_height="45.0dip" >
  105.             <EditText
  106.                 android:id="@id/passWord"
  107.                 android:layout_width="fill_parent"
  108.                 android:layout_height="45.0dip"
  109.                 android:background="@drawable/qz_bg_container_cell_bottom_normal"
  110.                 android:hint="密码"
  111.                 android:inputType="textPassword"
  112.                 android:maxLength="16"
  113.                 android:paddingLeft="15.0dip"
  114.                 android:paddingRight="15.0dip"
  115.                 android:singleLine="true"
  116.                 android:textColor="#ff000000"
  117.                 android:textColorHint="#ffbbbbbb"
  118.                 android:textSize="16.0dip" />
  119.             <ImageView
  120.                 android:id="@id/psw_close"
  121.                 android:layout_width="30.0dip"
  122.                 android:layout_height="45.0dip"
  123.                 android:layout_gravity="right|center"
  124.                 android:layout_marginRight="15.0dip"
  125.                 android:background="@android:color/transparent"
  126.                 android:clickable="true"
  127.                 android:scaleType="center"
  128.                 android:src="@drawable/qz_icon_close"
  129.                 android:visibility="invisible" />
  130.         </FrameLayout>
  131.         <Button
  132.             android:id="@id/login_btn"
  133.             android:layout_width="fill_parent"
  134.             android:layout_height="45.0dip"
  135.             android:layout_marginTop="12.0dip"
  136.             android:background="@drawable/qz_selector_login"
  137.             android:text="登 录"
  138.             android:textColor="#ffffffff"
  139.             android:textSize="20.0dip" />
  140.     </LinearLayout>
  141.     <ImageButton
  142.         android:id="@id/lineimg"
  143.         android:layout_width="fill_parent"
  144.         android:layout_height="1.0px"
  145.         android:layout_above="@id/reg_and_forget_password_layout"
  146.         android:background="#ffcfcfcf" />
  147.     <LinearLayout
  148.         android:id="@id/reg_and_forget_password_layout"
  149.         android:layout_width="fill_parent"
  150.         android:layout_height="49.0dip"
  151.         android:layout_alignParentBottom="true"
  152.         android:layout_alignParentRight="true"
  153.         android:orientation="horizontal" >
  154.         <Button
  155.             android:id="@id/forget_password_tv"
  156.             android:layout_width="0.0dip"
  157.             android:layout_height="fill_parent"
  158.             android:layout_weight="1.0"
  159.             android:autoLink="all"
  160.             android:background="@drawable/qz_selector_gray"
  161.             android:gravity="center"
  162.             android:text="找回密码"
  163.             android:textColor="#ff666666"
  164.             android:textSize="14.0dip" />
  165.         <ImageButton
  166.             android:layout_width="1.0px"
  167.             android:layout_height="fill_parent"
  168.             android:background="#ffcfcfcf" />
  169.         <Button
  170.             android:id="@id/reg_tv"
  171.             android:layout_width="0.0dip"
  172.             android:layout_height="fill_parent"
  173.             android:layout_weight="1.0"
  174.             android:autoLink="all"
  175.             android:background="@drawable/qz_selector_gray"
  176.             android:gravity="center"
  177.             android:text="新注册"
  178.             android:textColor="#ff666666"
  179.             android:textSize="14.0dip" />
  180.     </LinearLayout>
  181. </com.jun.qqzomelogin.InputMethodRelativeLayout>
(2)在Activity中实现OnSizeChangedListener,原理是设置该布局的paddingTop属性来控制子View的偏移。
  1. package com.jun.qqzomelogin;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.LinearLayout;
  6. import com.jun.qqzomelogin.InputMethodRelativeLayout.OnSizeChangedListenner;
  7. public class MainActivity extends Activity implements OnSizeChangedListenner{
  8.         private InputMethodRelativeLayout layout;  
  9.     private LinearLayout boot ;
  10.     private LinearLayout login_logo_layout_h ;
  11.     private LinearLayout login_logo_layout_v ;
  12.         @Override
  13.         protected void onCreate(Bundle savedInstanceState) {
  14.                 super.onCreate(savedInstanceState);
  15.                 setContentView(R.layout.activity_main);
  16.                 //取得InputMethodRelativeLayout组件
  17.                 layout = (InputMethodRelativeLayout) this.findViewById(R.id.loginpage) ;
  18.                 //设置监听事件
  19.         layout.setOnSizeChangedListenner(this) ;
  20.         //取得大LOGO布局
  21.         login_logo_layout_v = (LinearLayout) this.findViewById(R.id.login_logo_layout_v) ;
  22.         //取得小LOGO布局
  23.         login_logo_layout_h = (LinearLayout) this.findViewById(R.id.login_logo_layout_h) ;
  24.         
  25.         //取得找回密码和新注册布局
  26.         boot = (LinearLayout) this.findViewById(R.id.reg_and_forget_password_layout) ;
  27.        
  28.         }
  29.         /**
  30.          * 在Activity中实现OnSizeChangedListener,原理是设置该布局的paddingTop属性来控制子View的偏移
  31.          */
  32.         @Override
  33.         public void onSizeChange(boolean flag,int w ,int h) {  
  34.         if(flag){//键盘弹出时
  35.             layout.setPadding(0, -10, 0, 0);   
  36.             boot.setVisibility(View.GONE) ;
  37.             login_logo_layout_v.setVisibility(View.GONE) ;
  38.             login_logo_layout_h.setVisibility(View.VISIBLE) ;
  39.         }else{ //键盘隐藏时
  40.             layout.setPadding(0, 0, 0, 0); 
  41.             boot.setVisibility(View.VISIBLE) ;
  42.             login_logo_layout_v.setVisibility(View.VISIBLE) ;
  43.             login_logo_layout_h.setVisibility(View.GONE) ;
  44.         }
  45.     } 
  46. }
复制代码
注意:在AndroidManifest.xml中注册该Activity,需要注意的是:必须为该Activity设置android:windowSoftInputMode="adjustResize"属性,当windowSoftInputMode为adjustResiz时,Layout才会调用protected void onSizeChanged(int w, int h, int oldw, int oldh)这个方法,而且不能是全屏。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值