San*_*uys 219 events android android-softkeyboard
我想根据是否显示虚拟键盘来改变布局.我搜索过API和各种博客,但似乎找不到任何有用的东西.
可能吗?
谢谢!
Ped*_*iro 72
您必须自己处理配置更改.
http://developer.android.com/guide/topics/resources/runtime-changes.html#HandlingTheChange
样品:
// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show();
} else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show();
}
}
Run Code Online (Sandbox Code Playgroud)
然后只需更改某些视图的可见性,更新字段以及更改布局文件.
此解决方案不适用于软键盘,onConfigurationChanged
也不会调用软键盘.
ama*_*Bit 55
这可能不是最有效的解决方案.但是每次这对我都有用......我把这个函数称为我需要听软键的地方.
boolean isOpened = false;
public void setListenerToRootView() {
final View activityRootView = getWindow().getDecorView().findViewById(android.R.id.content);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // 99% of the time the height diff will be due to a keyboard.
Toast.makeText(getApplicationContext(), "Gotcha!!! softKeyboardup", 0).show();
if (isOpened == false) {
//Do two things, make the view top visible and the editText smaller
}
isOpened = true;
} else if (isOpened == true) {
Toast.makeText(getApplicationContext(), "softkeyborad Down!!!", 0).show();
isOpened = false;
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
注意:如果用户使用浮动键盘,此方法将导致问题.
Neb*_*cic 37
如果要处理从Activity中显示/隐藏IMM(虚拟)键盘窗口,则需要对布局进行子类化并覆盖onMesure方法(以便您可以确定测量的宽度和布局的测量高度).之后,通过setContentView()将子类布局设置为Activity的主视图.现在,您将能够处理IMM显示/隐藏窗口事件.如果这听起来很复杂,那就不是真的了.这是代码:
main.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<EditText
android:id="@+id/SearchText"
android:text=""
android:inputType="text"
android:layout_width="fill_parent"
android:layout_height="34dip"
android:singleLine="True"
/>
<Button
android:id="@+id/Search"
android:layout_width="60dip"
android:layout_height="34dip"
android:gravity = "center"
/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
现在在您的Activity声明布局的子类(main.xml)
public class MainSearchLayout extends LinearLayout {
public MainSearchLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.main, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("Search Layout", "Handling Keyboard Window shown");
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight){
// Keyboard is shown
} else {
// Keyboard is hidden
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以从代码中看到我们为子类构造函数中的Activity扩展布局
inflater.inflate(R.layout.main, this);
Run Code Online (Sandbox Code Playgroud)
现在只需为我们的Activity设置子类布局的内容视图.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainSearchLayout searchLayout = new MainSearchLayout(this, null);
setContentView(searchLayout);
}
// rest of the Activity code and subclassed layout...
}
Run Code Online (Sandbox Code Playgroud)
Hir*_*tel 28
我是这样做的:
添加OnKeyboardVisibilityListener
界面.
public interface OnKeyboardVisibilityListener {
void onVisibilityChanged(boolean visible);
}
Run Code Online (Sandbox Code Playgroud)
HomeActivity.java:
public class HomeActivity extends Activity implements OnKeyboardVisibilityListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up);
// Other stuff...
setKeyboardVisibilityListener(this);
}
private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {
final View parentView = ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
parentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
private boolean alreadyOpen;
private final int defaultKeyboardHeightDP = 100;
private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
private final Rect rect = new Rect();
@Override
public void onGlobalLayout() {
int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());
parentView.getWindowVisibleDisplayFrame(rect);
int heightDiff = parentView.getRootView().getHeight() - (rect.bottom - rect.top);
boolean isShown = heightDiff >= estimatedKeyboardHeight;
if (isShown == alreadyOpen) {
Log.i("Keyboard state", "Ignoring global layout change...");
return;
}
alreadyOpen = isShown;
onKeyboardVisibilityListener.onVisibilityChanged(isShown);
}
});
}
@Override
public void onVisibilityChanged(boolean visible) {
Toast.makeText(HomeActivity.this, visible ? "Keyboard is active" : "Keyboard is Inactive", Toast.LENGTH_SHORT).show();
}
}
Run Code Online (Sandbox Code Playgroud)
希望这会对你有所帮助.
Ste*_*fan 22
根据Nebojsa Tomcic的代码,我开发了以下RelativeLayout-Subclass:
import java.util.ArrayList;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
public class KeyboardDetectorRelativeLayout extends RelativeLayout {
public interface IKeyboardChanged {
void onKeyboardShown();
void onKeyboardHidden();
}
private ArrayList<IKeyboardChanged> keyboardListener = new ArrayList<IKeyboardChanged>();
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public KeyboardDetectorRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public KeyboardDetectorRelativeLayout(Context context) {
super(context);
}
public void addKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.add(listener);
}
public void removeKeyboardStateChangedListener(IKeyboardChanged listener) {
keyboardListener.remove(listener);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight) {
notifyKeyboardShown();
} else if (actualHeight < proposedheight) {
notifyKeyboardHidden();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void notifyKeyboardHidden() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardHidden();
}
}
private void notifyKeyboardShown() {
for (IKeyboardChanged listener : keyboardListener) {
listener.onKeyboardShown();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用......马克,当你的Activity的Soft Input Mode设置为"WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE"时,这个解决方案才会起作用
ale*_*ton 19
就像@ amalBit的答案一样,注册一个全局布局的监听器并计算dectorView的可见底部和它的底部的差异,如果差异大于某个值(猜测IME的高度),我们认为IME是:
final EditText edit = (EditText) findViewById(R.id.edittext);
edit.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (keyboardShown(edit.getRootView())) {
Log.d("keyboard", "keyboard UP");
} else {
Log.d("keyboard", "keyboard Down");
}
}
});
private boolean keyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
Run Code Online (Sandbox Code Playgroud)
高度阈值100是猜测的IME的最小高度.
这适用于adjustPan和adjustResize.
Jon*_*han 16
随着 androidx.core 1.5.0 的发布,这就是我在 Android 11 之前的设备中监听键盘显示/隐藏事件的方法。
等级:
implementation "androidx.core:core-ktx:1.5.0"
Run Code Online (Sandbox Code Playgroud)
分段:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val view = activity?.window?.decorView ?: return
ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
val showingKeyboard = insets.isVisible(WindowInsetsCompat.Type.ime())
if(showingKeyboard){
//do something
}
insets
}
}
Run Code Online (Sandbox Code Playgroud)
确保在视图销毁时删除侦听器以避免内存泄漏。该解决方案也仅在软件输入模式为 时有效adjustResize
,如果是adjustPan
,setOnApplyWindowInsetsListener 将不会触发,如果有人知道如何使其工作adjustPan
,请分享。
请注意,根据文档,
* When running on devices with API Level 29 and before, the returned value is an
* approximation based on the information available. This is especially true for the {@link
* Type#ime IME} type, which currently only works when running on devices with SDK level 23
* and above.
*
Run Code Online (Sandbox Code Playgroud)
insets.isVisible(ime) 只能在 SDK 级别高于 23 的设备上工作
小智 12
Nebojsa的解决方案几乎对我有用.当我在多行EditText中单击时,它知道键盘已经显示,但是当我开始在EditText内部输入时,actualHeight和proposedHeight仍然是相同的,所以它不知道键盘仍然显示.我做了一些修改来存储最大高度,它工作正常.这是修订后的子类:
public class CheckinLayout extends RelativeLayout {
private int largestHeight;
public CheckinLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.checkin, this);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
largestHeight = Math.max(largestHeight, getHeight());
if (largestHeight > proposedheight)
// Keyboard is shown
else
// Keyboard is hidden
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Run Code Online (Sandbox Code Playgroud)
qba*_*ait 10
我通过在我的自定义EditText中覆盖onKeyPreIme(int keyCode,KeyEvent事件)来解决这个问题.
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
//keyboard will be hidden
}
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*ert 10
不确定是否有人发布此内容.发现这个解决方案简单易用!.该SoftKeyboard类是gist.github.com.但是当键盘弹出/隐藏事件回调时,我们需要一个处理程序来在UI上正确地执行操作:
/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);
/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{
@Override
public void onSoftKeyboardHide()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
@Override
public void onSoftKeyboardShow()
{
// Code here
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Code here will run in UI thread
...
}
});
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
171214 次 |
最近记录: |