Android总结笔记04:仿QQ空间登录UI,解决软键盘弹出挡住输入框的问题

我们在开发Android应用中,登录和注册界面是少不了的,往往在做登录注册的时候如果给界面加一个LOGO,就有可能把用户名和密码框放在手机屏幕的中间或底部,这样当软键盘弹出的时候,就有可能挡住输入框(往往用户输完用户名和密码还要按返回键盘才能登录),这样用户体验是不好的,我曾今也为这种事情很头疼。首先说一下我原来想到过时想到的解决办法:

一、原来想到过的解决办法:

(1)、把登录和输入框让美工做在顶部,不要用LOGO图片类似于淘宝客户端(如下图):这样键盘弹出就不会影响到输入框,但是这样始终不是解决问题的方法(我原来常常让美工设计登录不要设计登录LOGO,呵呵比较自私)

Android总结笔记04:仿QQ空间登录UI,解决软键盘弹出挡住输入框的问题_第1张图片

(2)、在布局根结点中加入ScrollView结点,这样当看不见输入框的时候手动滚一下就可以看到,这种方法也可行

(3)、自己给View做一个平移动画,然后处理键盘弹出和消失view的移动,这种设计比较麻烦,而且当View移动了以后要重新计算View的坐标位置,否则拿不到控件的监听事件(表面上看View是移动了,可是移动的只是图片,View上面控件的事件还在原来的位置,比较郁闷)。

(4)、重写RelativeLayout获取当前屏幕高度,实现onMesure、onSizeChanged方法来实现。

废话不多说,我们今天采用第(4)种比较正规的方法来实现QQ空间登录页,先上图,无图无真相:以下分别是键盘没有弹出,和键盘弹出时登录情形(以下是我仿写的,布局用的就是QQ空间的布局)

Android总结笔记04:仿QQ空间登录UI,解决软键盘弹出挡住输入框的问题_第2张图片  Android总结笔记04:仿QQ空间登录UI,解决软键盘弹出挡住输入框的问题_第3张图片

二、实现代码

(1)、重写RelatvieLayout(自定义View),实现onMesure、onSizeChanged方法。

package com.jun.qqzomelogin;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Display;
import android.widget.RelativeLayout;
/**
 * 
 * @author junjun
 * 自定义布局解决键盘弹出挡住输入框的问题
 */
public class InputMethodRelativeLayout extends RelativeLayout {
	private int width;
	protected OnSizeChangedListenner onSizeChangedListenner;
	private boolean sizeChanged  = false; //变化的标志
	private int height;
	private int screenWidth; //屏幕宽度
	private int screenHeight; //屏幕高度

	public InputMethodRelativeLayout(Context paramContext,
			AttributeSet paramAttributeSet) {
		super(paramContext, paramAttributeSet);
		Display localDisplay = ((Activity) paramContext).getWindowManager()
				.getDefaultDisplay();
		this.screenWidth = localDisplay.getWidth() ;
		this.screenHeight = localDisplay.getHeight();
	}
	public InputMethodRelativeLayout(Context paramContext,
			AttributeSet paramAttributeSet, int paramInt) {
		super(paramContext, paramAttributeSet, paramInt);
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		this.width = widthMeasureSpec;
		this.height = heightMeasureSpec;
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	
	@Override
	public void onSizeChanged(int w, int h, int oldw,
			int oldh) {
		//监听不为空、宽度不变、当前高度与历史高度不为0 
		if ((this.onSizeChangedListenner!= null) && (w == oldw) && (oldw != 0)
				&& (oldh != 0)) {
			if ((h >= oldh)
					|| (Math.abs(h - oldh) <= 1 * this.screenHeight / 4)) {
				if ((h <= oldh)
						|| (Math.abs(h - oldh) <= 1 * this.screenHeight / 4))
					return;
				this.sizeChanged  = false;
			} else {
				this.sizeChanged  = true;
			}
			this.onSizeChangedListenner.onSizeChange(this.sizeChanged ,oldh, h);
			measure(this.width - w + getWidth(), this.height
					- h + getHeight());
		}
	}
	/**
	 * 设置视图偏移的监听事件
	 * @param paramonSizeChangedListenner
	 */
	public void setOnSizeChangedListenner(
			InputMethodRelativeLayout.OnSizeChangedListenner paramonSizeChangedListenner) {
		this.onSizeChangedListenner = paramonSizeChangedListenner;
	}
	/**
	 * 视图偏移的内部接口
	 * @author junjun
	 *
	 */
	public abstract interface OnSizeChangedListenner {
		public abstract void onSizeChange(boolean paramBoolean, int w,int h);
	}
}

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




    
		
        

            

            
        
		
        

            

            
        

        

            

            

            
        

        

            

            
        

        

(2)、在Activity中实现OnSizeChangedListener,原理是设置该布局的paddingTop属性来控制子View的偏移。

package com.jun.qqzomelogin;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import com.jun.qqzomelogin.InputMethodRelativeLayout.OnSizeChangedListenner;

/**
 * 
 * @author junjun
 *
 */
public class MainActivity extends Activity implements OnSizeChangedListenner{

	private InputMethodRelativeLayout layout;  
    private LinearLayout boot ;
    private LinearLayout login_logo_layout_h ;
    private LinearLayout login_logo_layout_v ;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//取得InputMethodRelativeLayout组件
		layout = (InputMethodRelativeLayout) this.findViewById(R.id.loginpage) ;
		//设置监听事件
        layout.setOnSizeChangedListenner(this) ;
        //取得大LOGO布局
        login_logo_layout_v = (LinearLayout) this.findViewById(R.id.login_logo_layout_v) ;
        //取得小LOGO布局
        login_logo_layout_h = (LinearLayout) this.findViewById(R.id.login_logo_layout_h) ;
        
        //取得找回密码和新注册布局
        boot = (LinearLayout) this.findViewById(R.id.reg_and_forget_password_layout) ;
       
	}

	/**
	 * 在Activity中实现OnSizeChangedListener,原理是设置该布局的paddingTop属性来控制子View的偏移
	 */
	@Override
	public void onSizeChange(boolean flag,int w ,int h) {  
        if(flag){//键盘弹出时
            layout.setPadding(0, -10, 0, 0);   
            boot.setVisibility(View.GONE) ;
            login_logo_layout_v.setVisibility(View.GONE) ;
            login_logo_layout_h.setVisibility(View.VISIBLE) ;
        }else{ //键盘隐藏时
            layout.setPadding(0, 0, 0, 0); 
            boot.setVisibility(View.VISIBLE) ;
            login_logo_layout_v.setVisibility(View.VISIBLE) ;
            login_logo_layout_h.setVisibility(View.GONE) ;
        }
    }  
 
	
}

注意:在AndroidManifest.xml中注册该Activity,需要注意的是:必须为该Activity设置android:windowSoftInputMode="adjustResize"属性,当windowSoftInputMode为adjustResiz时,Layout才会调用protected void onSizeChanged(int w, int h, int oldw, int oldh)这个方法,而且不能是全屏。

好了就到这里,希望对你有帮助,最后附上源码地址:http://download.csdn.net/detail/android0012345/5830639

你可能感兴趣的:(Android进阶篇,QQ空间,登录,软键盘)