?????? 在开发Android应用程序时,经常会有登录界面,无非是输入用户名、密码进行登录。当输入框获取焦点时,会弹出软键盘进行输入,如果输入框和登录按钮布局在整个布局文件的中间或靠下,势必会被软键盘遮挡,让人十分郁闷。网络上的解决方法无非也就那么三种:
第一、将登录框放在布局文件的顶端,软键盘不会遮挡;这种方案虽然能解决问题,但相当不灵活;
?
第二、在布局文件中根节点处加入ScrollView控件;
?
第三、这是我今天要讲的内容
?
首先,继承RelativeLayout,获取当前屏幕高度,实现onMesure、onSizeChanged方法;
?
其次,为自定义的Layout添加视图偏移的监听器
?
最后、在Activity当中实现监听
?
代码
?
- public?class?InputMethodRelativeLayout?extends?RelativeLayout?{??
- ????private?int?width;??
- ??????
- ????private?int?height;??
- ??????
- ????private?int?screenHeight;??
- ??????
- ????private?boolean?sizeChanged?=?false;??
- ??????
- ????private?OnSizeChangedListener?onSizeChangedListener;??
- ??????
- ????public?InputMethodRelativeLayout(Context?context,?AttributeSet?attrs,??
- ????????????int?defStyle)?{??
- ????????super(context,?attrs,?defStyle);??
- ????????Display?localDisplay?=?((Activity)context).getWindowManager().getDefaultDisplay();??
- ????????screenHeight?=?localDisplay.getHeight();??
- ????????//?TODO?Auto-generated?constructor?stub??
- ????}??
- ??
- ????public?InputMethodRelativeLayout(Context?context,?AttributeSet?attrs)?{??
- ????????super(context,?attrs);??
- ????????//?TODO?Auto-generated?constructor?stub??
- ????}??
- ??
- ????public?InputMethodRelativeLayout(Context?context)?{??
- ????????super(context);??
- ????????//?TODO?Auto-generated?constructor?stub??
- ????}??
- ??
- ????@Override??
- ????protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????this.width?=?widthMeasureSpec;??
- ????????this.height?=?heightMeasureSpec;??
- ????????super.onMeasure(widthMeasureSpec,?heightMeasureSpec);??
- ????}??
- ??
- ????@Override??
- ????protected?void?onSizeChanged(int?w,?int?h,?int?oldw,?int?oldh)?{??
- ????????//?TODO?Auto-generated?method?stub??
- //监听不为空、宽度不变、当前高度与历史高度不为0??
- if(this.onSizeChangedListener?!=?null?&&?w?==?oldw?&&?h?!=?0?&&?oldh?!=?0){??
- ????????if(h?>=?oldh?||?(Math.abs(h?-?oldh)?<=?1?*?this.screenHeight?/?4)){??
- ????????????sizeChanged?=?false;??
- ????????}else?if(h?<=?oldh?||?(Math.abs(h?-?oldh)?<=?1?*?this.screenHeight?/?4)){??
- ????????????sizeChanged?=?true;??
- ????????}??
- ????????this.onSizeChangedListener.onSizeChange(sizeChanged);??
- ????????measure(this.width?-?w?+?getWidth(),?this.height?-?h?+?getHeight());??
- ????}??
- }??
- ??
- /**??
- [email protected]:?setOnSizeChangedListener??
- [email protected]:?为当前布局设置onSizeChanged监听器??
- [email protected]?
- [email protected]?
- */???
- public?void?setOnSizeChangedListener(OnSizeChangedListener?sizeChangedListener)?{??
- ????this.onSizeChangedListener?=?sizeChangedListener;??
- }??
- ??
- ??
- public?abstract?interface?OnSizeChangedListener{??
- ??????
- ????public?abstract?void?onSizeChange(boolean?flag);??
- }??
在Activity中实现OnSizeChangedListener,原理是设置该布局的paddingTop属性来控制子View的偏移,如下:
- public?class?OALogin?extends?BaseActivity?implements?InputMethodRelativeLayout.OnSizeChangedListener{??
- ??????
- ????@InjectView(R.id.loginpage)??
- ????private?InputMethodRelativeLayout?layout;??
- ??????
- ????@Inject??
- ????private?InputMethodManager?inputMethodManager;??
- ????private?float?density;??
- ????@Override??
- ????protected?void?onCreate(Bundle?savedInstanceState)?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????super.onCreate(savedInstanceState);??
- ????????setContentView(R.layout.login_page);??
- ????????getSupportActionBar().hide();??
- ????????density?=?getResources().getDisplayMetrics().density;??
- ????????layout.setOnSizeChangedListener(this);??
- ????}??
- ??
- ????@Override??
- ????public?void?onSizeChange(boolean?flag)?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????if(flag){??
- ????????????layout.setPadding(0,?-159,?0,?0);??
- ????????}else??
- ????????????layout.setPadding(0,?0,?0,?0);??
- ????}??
- ??
- ????@Override??
- ????public?boolean?onTouchEvent(MotionEvent?event)?{??
- ????????//?TODO?Auto-generated?method?stub??
- ????????if(event.getAction()?==?MotionEvent.ACTION_UP){??
- ????????????inputMethodManager.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(),0);??
- ????????}??
- ????????return?super.onTouchEvent(event);??
- ????}??
在AndroidManifest.xml中注册该Activity,需要注意的是:必须为该Activity设置android:windowSoftInputMode="adjustResize"属性,当windowSoftInputMode为adjustResiz时,Layout才会调用protected void onSizeChanged(int w, int h, int oldw, int oldh)这个方法。
?
俗话说,无图无真相,直接上图(借助了QQ2012的登录界面)
各位体会下吧!