您的位置:首页 > 移动开发 > Android开发

Android 软键盘弹出自动移动布局

2016-06-21 15:50 465 查看


2行代码搞定软键盘布局上移

当我们在使用登录界面的时候,软键盘弹出经常会挡住输入框或者登录按钮

一般应用都没有处理,处理的也是很粗糙,所以我写了一个自定义控件解决该问题。

想移动谁就移动谁,so easy !!!!!

/**
* 类描述: 监听布局Layout变化,进行移动整体布局的自定义控件
* 创建人: chenyang
* QQ: 454725164
* 邮箱: inke88@163.com
* 创建时间: 2016年06月17日 15时35分
* 修改人:
* 修改时间:
* 修改备注:
* 版本:
*/
public class KeyboardMoveLayout extends LinearLayout {
private OnSizeChangedListener mChangedListener;
private boolean isShowKeyboard = false;

public KeyboardMoveLayout(Context context) {
super(context);
}

public KeyboardMoveLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public KeyboardMoveLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (null != mChangedListener && 0 != oldw && 0 != oldh) {
if (h < oldh) {
isShowKeyboard = true;
} else {
isShowKeyboard = false;
}
mChangedListener.onChanged(isShowKeyboard);
}
}

public void setOnSizeChangedListener(OnSizeChangedListener listener) {
mChangedListener = listener;
}

public interface OnSizeChangedListener {
void onChanged(boolean showKeyboard);
}
}

上面的KeyboardMoveLayout自定义控件主要用于监听软键盘的弹出或者关闭,该自定义控件一般放在一级根布局或者二级根布局。

想移动谁,就把ScrollView包裹在谁身上

<?xml version="1.0" encoding="utf-8"?>
<test.inke.com.test.KeyboardMoveLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="test.inke.com.test.MainActivity">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ff0000"></LinearLayout>

<ScrollView
android:id="@+id/sc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<LinearLayout
android:id="@+id/ll_move"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<EditText
android:id="@+id/et1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:text="1111" />

<EditText
android:id="@+id/et2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="2222" />

<EditText
android:id="@+id/et3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="3333" />

<EditText
android:id="@+id/et4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="4444" />

<EditText
android:id="@+id/et5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="5555" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxvxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />

<Button
android:id="@+id/bt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="xxxxxxxx" />
</LinearLayout>
</ScrollView>
</test.inke.com.test.KeyboardMoveLayout>


上面是demo的xml布局。

以下是自定义控件的核心工具类

/**
* 类描述: 自动移动的工具类
* 创建人: chenyang
* QQ: 454725164
* 邮箱: inke88@163.com
* 创建时间: 2016年06月17日 15时40分
* 修改人:
* 修改时间:
* 修改备注:
* 版本:
*/
public class AutoMoveUtis {
public static AutoMoveUtis autoMoveUtis;

private AutoMoveUtis() {
}

public static AutoMoveUtis getInstance() {
if (autoMoveUtis == null) {
synchronized (AutoMoveUtis.class) {
if (autoMoveUtis == null) {
autoMoveUtis = new AutoMoveUtis();
}
}
}
return autoMoveUtis;
}

//保存View和移动的距离信息
public static Map<Integer, MoveLayoutModel> moveMaps = new HashMap<Integer, MoveLayoutModel>();
private int currentFocus = -1;//当前焦点
private int oldFocus = -1;//上一次焦点
private Handler handler = new Handler();
private boolean isAlreadJudgeMove;//是否已经判断移动,防止多次移动,损耗性能。
private int delayTime = 100;//延迟执行滚动时间。
private ScrollView scrollView;

/**
* 监听软件盘是否弹出
*
* @param rootView
* @param scrollView
*/
public void setRootAndScrollView(KeyboardMoveLayout rootView, ScrollView scrollView) {
this.scrollView = scrollView;
rootView.setOnSizeChangedListener(new KeyboardMoveLayout.OnSizeChangedListener() {
@Override
public void onChanged(boolean showKeyboard) {
if (showKeyboard && !isAlreadJudgeMove) {
moveHeight();
}
}
});
}

/**
* 监听焦点变化
*/
public View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean isFocused) {
if (isFocused) {
currentFocus = view.getId();//获取view的id
if (AutoMoveUtis.moveMaps.containsKey(view.getId())) {
//焦点变化在触发移动
if (oldFocus != currentFocus) {
isAlreadJudgeMove = true;
moveHeight();//移动
}
}
} else {
// 此处为失去焦点时的处理内容
}
}
};

/**
* 默认移动自身EditText的高度
*
* @param view
*/
public void setAutoMoveEditText(final EditText view) {
view.post(new Runnable() {
@Override
public void run() {
moveMaps.put(view.getId(), new MoveLayoutModel(view.getId(), view.getHeight()));
}
});
view.setOnFocusChangeListener(onFocusChangeListener);
}

/**
* 移动自身EditText的高度的倍数
*
* @param view
* @param ratioHeight
*/
public void setAutoMoveEditText(final EditText view, final float ratioHeight) {
view.post(new Runnable() {
@Override
public void run() {
moveMaps.put(view.getId(), new MoveLayoutModel(view.getId(), (int) (view.getHeight() * ratioHeight)));
}
});
view.setOnFocusChangeListener(onFocusChangeListener);
}

/**
* 移动随意的距离
*
* @param view
* @param moveDistance
*/
public void setAutoMoveEditText(final EditText view, final int moveDistance) {
view.post(new Runnable() {
@Override
public void run() {
moveMaps.put(view.getId(), new MoveLayoutModel(view.getId(), moveDistance));
}
});
view.setOnFocusChangeListener(onFocusChangeListener);
}

/**
* 移动到ScrollView的底部
*
* @param view
*/
public void setAutoMoveButtomEditText(final EditText view) {
view.post(new Runnable() {
@Override
public void run() {
moveMaps.put(view.getId(), new MoveLayoutModel(view.getId(), view.getHeight(), MoveLayoutModel.MOVE_BOTTOM));
}
});
view.setOnFocusChangeListener(onFocusChangeListener);
}

/**
* 移动高度
*/
private void moveHeight() {
//初始状态不移动
if (currentFocus == -1) {
return;
}
//根据设置的模式,进行移动高度或者移动到底部
if (AutoMoveUtis.moveMaps.containsKey(currentFocus)) {
MoveLayoutModel moveLayoutModel = AutoMoveUtis.moveMaps.get(currentFocus);
if (moveLayoutModel.getMoveStatus() == MoveLayoutModel.MOVE_DISTANCE) {
moveDistance(moveLayoutModel.getMoveDistance());
} else if (moveLayoutModel.getMoveStatus() == MoveLayoutModel.MOVE_BOTTOM) {
moveButtom();
}
}
oldFocus = currentFocus;
}

// 移动距离
private void moveDistance(final int moveHeight) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
isAlreadJudgeMove = false;
scrollView.scrollTo(0, moveHeight);//滚动到底部
}
}, delayTime);
}

// 移动到底部
private void moveButtom() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
isAlreadJudgeMove = false;
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}, delayTime);
}

}


最后需要在Activity中增加<span style="font-size:32px;color:#ff0000;">android:windowSoftInputMode="adjustResize|stateHidden"</span>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.inke.com.test">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize|stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

测试类:

/**
* 类描述:
* 创建人: chenyang
* QQ: 454725164
* 邮箱: inke88@163.com
* 创建时间: 2016年06月17日 15时31分
* 修改人:
* 修改时间:
* 修改备注:
* 版本:
*/
public class MainActivity extends Activity {
private EditText et1, et2, et3, et4, et5;
private ScrollView scrollView;
private KeyboardMoveLayout rootView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
rootView = (KeyboardMoveLayout) findViewById(R.id.ll);
scrollView = (ScrollView) findViewById(R.id.sc);
et1 = (EditText) findViewById(R.id.et1);
et2 = (EditText) findViewById(R.id.et2);
et3 = (EditText) findViewById(R.id.et3);
et4 = (EditText) findViewById(R.id.et4);
et5 = (EditText) findViewById(R.id.et5);

// 注入根布局和ScrollView控件
AutoMoveUtis.getInstance().setRootAndScrollView(rootView, scrollView);
//焦点移动到哪个EditText,进行布局滑动就注入哪个EditText
AutoMoveUtis.getInstance().setAutoMoveEditText(et1);//移动EditText自身高度
AutoMoveUtis.getInstance().setAutoMoveEditText(et2, 2f);//移动EditText自身高度的倍数
AutoMoveUtis.getInstance().setAutoMoveEditText(et3, 30);//移动随意高度
AutoMoveUtis.getInstance().setAutoMoveEditText(et4, 150);//移动随意高度
AutoMoveUtis.getInstance().setAutoMoveButtomEditText(et5);//移动到底部
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: