在 Fragment 中实现 onKeyPreIme(int keyCode, KeyEvent event)
Posted
技术标签:
【中文标题】在 Fragment 中实现 onKeyPreIme(int keyCode, KeyEvent event)【英文标题】:Implementing onKeyPreIme(int keyCode, KeyEvent event) in Fragment 【发布时间】:2012-11-15 11:22:49 【问题描述】:我不知道如何在 Fragment
中实现 onKeyPreIme(int keyCode, KeyEvent event)
。
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event)
if (keyCode == KeyEvent.KEYCODE_BACK &&
event.getAction() == KeyEvent.ACTION_UP)
// do your stuff
return false;
return super.dispatchKeyEvent(event);
我尝试了很多,但没有任何效果。另外,我在 Google 或 Stack Overflow 上找不到任何东西。我想在按下返回键并且软键盘启动时执行一个操作。在我的EditText
s 上设置onKeyListener
不起作用,因为当软键盘启动时不会调用KeyEvent.KEYCODE_BACK
。感谢任何帮助和源代码。
【问题讨论】:
感谢您的代码,了解返回super.dispatchKeyEvent(event);
活动的后退按钮将起作用,这很有帮助!
【参考方案1】:
这是我的解决方案,对我来说效果很好,但每个人的需求不同。
首先,我将 EditText 子类化并连接了一个侦听器(Google 应该将其设为默认值)
public class ListenerEditText extends EditText
private KeyImeChange keyImeChangeListener;
public ListenerEditText(Context context, AttributeSet attrs)
super(context, attrs);
public void setKeyImeChangeListener(KeyImeChange listener)
keyImeChangeListener = listener;
public interface KeyImeChange
public void onKeyIme(int keyCode, KeyEvent event);
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event)
if(keyImeChangeListener != null)
keyImeChangeListener.onKeyIme(keyCode, event);
return false;
然后你可以像这样从任何地方附加一个监听器:
myListenerEditText.setKeyImeChangeListener(new KeyImeChange()
@Override
public void onKeyIme(int keyCode, KeyEvent event)
// All keypresses with the keyboard open will come through here!
// You could also bubble up the true/false if you wanted
// to disable propagation.
);
【讨论】:
这看起来是最好的答案,因为它实际上可以覆盖 onKeyPreIme。我不想问,但我在让它工作时遇到了问题。我扩展了 AutoCompleteTextView 并在我的活动(您的第二个代码块)中的 onKeyIme(...) 中添加了一个返回语句。除此之外,我已经完全复制了您的代码,并在“return”语句和新类中的每个方法上设置了断点。调用 setKeyImeChangeListener 并初始化 keyImeChangeListener,但是,按下键时永远不会调用 onKeyIme()。有什么想法可以从哪里开始进行故障排除? 好的,我想我明白了。这些键盘事件适用于物理键盘,而不是软键盘。任何人都可以确认吗?谢谢。 顺便说一句,我仍然是 android 的学生,所以感谢这段代码。我能够使用它来覆盖 onFilterComplete 方法。 Android 不为这些事件提供侦听器似乎有点愚蠢。 我也没有看到我的 onKeyIme 方法被调用。这对软键盘有用吗?【参考方案2】:我能够通过对与键盘输入相关的 EditText 视图进行子类化来实现 onKeyPreIme。目标是制作用户必须输入密码或离开应用程序的自定义锁屏。当用户点击“键盘向下”按钮时,键盘不会消失。
确保为子类 EditText 创建一个单独的 .java 文件。另外,请务必使用下面代码中的构造函数(必须通过 AttrubuteSet)。
我意识到我的 onKeyPreIme 实现可能与您的不匹配,但它确实演示了如何在 InputMethodManager 执行此操作之前拦截键盘事件。
我希望这会有所帮助。
屏幕截图 UserLockActivity
EditText 子类
public class LockEditText extends EditText
/* Must use this constructor in order for the layout files to instantiate the class properly */
public LockEditText(Context context, AttributeSet attrs)
super(context, attrs);
// TODO Auto-generated constructor stub
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event)
// Return true if I handle the event:
// In my case i want the keyboard to not be dismissible so i simply return true
// Other people might want to handle the event differently
System.out.println("onKeyPreIme " +event);
return true;
UserLockActivity.java
public class UserLockActivity extends Activity
private LockEditText editText1;
private LockEditText editText2;
private LockEditText editText3;
private LockEditText editText4;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_lock);
editText1 = (LockEditText) findViewById(R.id.lock_text_1);
editText2 = (LockEditText) findViewById(R.id.lock_text_2);
editText3 = (LockEditText) findViewById(R.id.lock_text_3);
editText4 = (LockEditText) findViewById(R.id.lock_text_4);
setupTextChangedListener(editText1);
setupTextChangedListener(editText2);
setupTextChangedListener(editText3);
setupTextChangedListener(editText4);
// A method to bring out the keyboard when the view appears
setFocusOnEditText(editText1);
public void setFocusOnEditText(LockEditText editText)
editText.clearFocus();
editText.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
public void setupTextChangedListener(LockEditText editText)
editText.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
@Override
public void afterTextChanged(Editable arg0)
// TODO Auto-generated method stub
@Override
public void beforeTextChanged(CharSequence arg0, int arg1,int arg2, int arg3)
// TODO Auto-generated method stub
);
activity_user_lock.xml 布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".UserLockActivity" >
<TextView
android:id="@+id/main_lock_text"
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:paddingTop="60dp"
android:paddingBottom="20dp"
android:text="@string/enter_passcode"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:id="@+id/lock_input_layout"
android:layout_
android:layout_
android:layout_below="@+id/main_lock_text"
android:orientation="horizontal" >
<com.yourpackage.yourappname.LockEditText
android:id="@+id/lock_text_1"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:ems="10"
android:inputType="numberPassword"
android:textSize="30sp"
android:gravity="center_horizontal"
android:textStyle="bold" >
</com.yourpackage.yourappname.LockEditText>
<com.yourpackage.yourappname.LockEditText
android:id="@+id/lock_text_2"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:ems="10"
android:inputType="numberPassword"
android:textSize="30sp"
android:gravity="center_horizontal"
android:textStyle="bold" >
</com.yourpackage.yourappname.LockEditText>
<com.yourpackage.yourappname.LockEditText
android:id="@+id/lock_text_3"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:ems="10"
android:inputType="numberPassword"
android:textSize="30sp"
android:gravity="center_horizontal"
android:textStyle="bold">
</com.yourpackage.yourappname.LockEditText>
<com.yourpackage.yourappname.LockEditText
android:id="@+id/lock_text_4"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:ems="10"
android:inputType="numberPassword"
android:textSize="30sp"
android:gravity="center_horizontal"
android:textStyle="bold" >
</com.yourpackage.yourappname.LockEditText>
</LinearLayout>
<TextView
android:id="@+id/textView1"
android:layout_
android:layout_
android:layout_below="@+id/lock_input_layout"
android:layout_centerHorizontal="true"
android:text="text" />
</RelativeLayout>
【讨论】:
它与我的意图不符,但你的想法很有创意,所以我会接受你的回答 精湛的@i2097i。谢谢哥们:) @i2097i 我有一个问题。 android中是否有任何方法可以以编程方式从EditText
移除焦点?
@Perry ***.com/questions/5056734/…
此解决方案效果很好,但它适用于活动。要添加到 Fragment,您必须在实例化 InputMethodManager 时获取活动。所以对于这一行: InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);添加一个getActivity。在 getSystemService 之前。所以它看起来像这样: InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);【参考方案3】:
我无法弄清楚如何实现 onKeyPreIME,但我能够在键盘消失后使用以下代码执行操作:
您需要更改比较 heightDiff > 200。这个比较对我有用,因为我有一个滚动视图。
fragmentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
@Override
public void onGlobalLayout()
if(getView() != null)
int heightDiff = getView().getRootView().getHeight() - getView().getHeight();
if (heightDiff < 200)
rlupdate.setVisibility(RelativeLayout.VISIBLE);
else
rlupdate.setVisibility(RelativeLayout.GONE);
);
【讨论】:
【参考方案4】:这是 Deminetix 提供的更完整的答案代码。
我已经使用 Deminetix 的答案来过滤 android 上的手持条形码阅读器并得到结果。
为了使它只能在带有按钮的屏幕上使用,我添加了一个带有 android:textColor="#FF000000" android:background="#00FFFFFF" android:enabled="false" 的 EditText 禁用的 EditText 仍会收到键盘事件。
我可以选择使用以下方法隐藏软件键盘,但禁用 EditText 后就不需要了。
//InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//imm.showSoftInput(textPatientId, InputMethodManager.HIDE_IMPLICIT_ONLY);
MainActivity.java:
package com.doodkin.keyboardtest;
import com.doodkin.keyboardtest.ListenerEditText.KeyImeChange;
import android.os.Bundle;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnKeyListener;
import android.widget.EditText;
public class MainActivity extends Activity
private static final String TAG = "keyboard test";
//private EditText editText1;
ListenerEditText editText1=null;
public String barcodebuffer="";
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText1 = (ListenerEditText) findViewById(R.id.editText1);
editText1.setKeyImeChangeListener(new KeyImeChange()
@Override
public boolean onKeyIme(int keyCode, KeyEvent event)
String deviceName=event.getDevice().getName();
int keyboardType=event.getDevice().getKeyboardType();
int indexof=deviceName.indexOf("USB");
if(indexof!=-1 && keyboardType==InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC)
if(event.getKeyCode()==KeyEvent.KEYCODE_ENTER)
if(barcodebuffer!="")
Log.d(TAG, "filterBarcodeKeys Chars Flush: " + barcodebuffer );
barcodebuffer="";
else
barcodebuffer+=Character.toString((char)event.getUnicodeChar());
//Log.d(TAG, "filterBarcodeKeys Char: " + Character.toString((char)event.getUnicodeChar()) );
return true;
return false;
);
@Override
public boolean onCreateOptionsMenu(Menu menu)
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_
android:layout_
android:text="@string/hello_world" />
<com.doodkin.keyboardtest.ListenerEditText
android:id="@+id/editText1"
android:layout_
android:layout_
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:ems="10" >
<requestFocus />
</com.doodkin.keyboardtest.ListenerEditText>
<Button
android:id="@+id/button1"
android:layout_
android:layout_
android:layout_alignLeft="@+id/editText1"
android:layout_below="@+id/editText1"
android:layout_marginTop="69dp"
android:text="Button" />
</RelativeLayout>
ListenerEditText.java:
package com.doodkin.keyboardtest;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.EditText;
/*
* example:
myListenerEditText.setKeyImeChangeListener(new KeyImeChange()
@Override
public boolean onKeyIme(int keyCode, KeyEvent event)
// All keypresses with the keyboard open will come through here!
// You could also bubble up the true/false if you wanted
// to disable propagation.
);
*/
public class ListenerEditText extends EditText
private KeyImeChange keyImeChangeListener;
public ListenerEditText(Context context, AttributeSet attrs)
super(context, attrs);
public void setKeyImeChangeListener(KeyImeChange listener)
keyImeChangeListener = listener;
public interface KeyImeChange
public boolean onKeyIme(int keyCode, KeyEvent event);
@Override
public boolean onKeyPreIme (int keyCode, KeyEvent event)
if(keyImeChangeListener != null)
return keyImeChangeListener.onKeyIme(keyCode, event);
return false;
【讨论】:
我找不到 setKeyImeChangeListener 方法。 它属于 - 公共类 ListenerEditText 扩展了 EditText。这是我开发的课程,您可以在上面看到。坦率地说,很久以前不知道我该如何帮助你。我不记得了。以上是关于在 Fragment 中实现 onKeyPreIme(int keyCode, KeyEvent event)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Fragment 中实现 Google Maps 并使用 GoogleMap 对象?
Android Studio:如何从 Fragment 在 ActionBar 中实现后退按钮