标题翻译
Samsung keyboard backspace not working with SearchView
问题
在我的安卓应用中使用SearchView时,三星设备上使用三星键盘的用户无法使用退格按钮。三星键盘中的退格按钮在EditText和其他任何输入视图上的效果都很好,但在SearchView上却不起作用。我尝试过在用户按下退格键的时候检测并手动删除一个字母,但这也没有起作用。这是三星键盘的问题吗?我该如何解决这个问题?
英文翻译
When using SearchView in my android app, Samsung devices users with samsung keyboard only can't use the backspace button.
Backspace button in samsung keyboard is working fine with EditText and any other input view, except SearchView.
I have tried to detect when the user press the backspace key code and remove one letter manualy, but not working also.
Is it a problem with Samsung keyboard? How can I overcome this problem?
答案1
得分: 0
我知道这是一篇旧帖子,但我刚遇到了相同的问题,所以我会贴出我的解决方案。问题是由于 SearchView
使用了扩展的 EditText
,覆盖了 onKeyPreIme
方法,但没有传递 KeyEvent.KEYCODE_BACK
事件。解决方案并不完全安全,因为我必须重写了一个受限 API,但这不应该是问题。
解决方案使用了 androidx 库的版本,但可以根据旧的 appcompat 库进行编辑。
首先,我们创建一个名为 MySearchViewSearchAutoComplete
的类,该类覆盖了内部静态类 androidx.appcompat.widget.SearchView.SearchAutoComplete
。该类重写了 onKeyPreIme
方法,当需要时,拦截 KeyEvent.KEYCODE_BACK
事件,将其替换为 KeyEvent.KEYCODE_DEL
事件,并直接发送到编辑框中。
以下是代码:
package com.example.widget.search;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
@SuppressLint("RestrictedApi")
public class MySearchViewSearchAutoComplete extends androidx.appcompat.widget.SearchView.SearchAutoComplete {
boolean _isNonTouch;
boolean _isIgnore;
public MySearchViewSearchAutoComplete(Context context) {
super(context);
init(context);
}
public MySearchViewSearchAutoComplete(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MySearchViewSearchAutoComplete(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
_isNonTouch = context.getResources().getConfiguration().touchscreen == android.content.res.Configuration.TOUCHSCREEN_NOTOUCH;
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (_isNonTouch && keyCode == KeyEvent.KEYCODE_BACK) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
_isIgnore = getSelectionStart() == 0 && getSelectionEnd() == 0;
}
if (!_isIgnore) {
event = new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), KeyEvent.KEYCODE_DEL, event.getRepeatCount(), event.getMetaState(), event.getDeviceId(), event.getScanCode(), event.getFlags(), event.getSource());
dispatchKeyEvent(event);
return true;
}
}
return super.onKeyPreIme(keyCode, event);
}
}
然后,我们重写 abc_search_view
布局,使用上面扩展的类。我们只需更改 EditText
类为我们上面扩展的类。创建一个名为 abc_search_view.xml
的布局文件。以下是代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- ... 其他布局元素 ... -->
<LinearLayout
android:id="@+id/search_edit_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip"
android:layout_weight="1"
android:layoutDirection="locale"
android:orientation="horizontal">
<!-- ... 其他布局元素 ... -->
<view
android:id="@+id/search_src_text"
class="com.example.widget.search.MySearchViewSearchAutoComplete"
android:layout_width="0dp"
android:layout_height="36dip"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@null"
android:dropDownAnchor="@id/search_edit_frame"
android:dropDownHeight="wrap_content"
android:dropDownHorizontalOffset="0dip"
android:dropDownVerticalOffset="0dip"
android:ellipsize="end"
android:imeOptions="actionSearch"
android:inputType="text|textAutoComplete|textNoSuggestions"
android:paddingLeft="@dimen/abc_dropdownitem_text_padding_left"
android:paddingRight="@dimen/abc_dropdownitem_text_padding_right"
android:singleLine="true" />
<!-- ... 其他布局元素 ... -->
</LinearLayout>
<!-- ... 其他布局元素 ... -->
</LinearLayout>
至此,应该就可以了。
英文翻译
I know this is old post, but I just had the same issue,so I will post my solution. The issue is caused by SearchView
using an extended EditText
that overrides onKeyPreIme
, and does not pass KeyEvent.KEYCODE_BACK
events.<br>
The solution I used, is not entirely safe, as I have to overide a RestrictedAPI, but it shouldn't be an issue.<br>
The solution uses the androidx library version, but can be edited for the older appcompat library.<p>
First we create a class MySearchViewSearchAutoComplete
that overrides the internal static androidx.appcompat.widget.SearchView.SearchAutoComplete
class. This class overrides onKeyPreIme
, and when needed, intercepts KeyEvent.KEYCODE_BACK
events, swaps them for KeyEvent.KEYCODE_DEL
events, and dispatches them directly to the EditBox. </p>
Here is the code;
package com.example.widget.search;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
@SuppressLint("RestrictedApi")
public class MySearchViewSearchAutoComplete extends androidx.appcompat.widget.SearchView.SearchAutoComplete
{
boolean _isNonTouch;
boolean _isIgnore;
public MySearchViewSearchAutoComplete(Context context)
{
super(context);
init(context);
}
public MySearchViewSearchAutoComplete(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
public MySearchViewSearchAutoComplete(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(context);
}
private void init(Context context)
{
_isNonTouch = context.getResources().getConfiguration().touchscreen == android.content.res.Configuration.TOUCHSCREEN_NOTOUCH;
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event)
{
if (_isNonTouch && keyCode == KeyEvent.KEYCODE_BACK)
{
if (event.getAction() == KeyEvent.ACTION_DOWN) // on ActionUp it may already be empty, but we should treat it as not empty
{
_isIgnore = getSelectionStart() == 0 && getSelectionEnd() == 0;
}
if (!_isIgnore)
{
event = new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), KeyEvent.KEYCODE_DEL, event.getRepeatCount(), event.getMetaState(), event.getDeviceId(), event.getScanCode(), event.getFlags(), event.getSource());
dispatchKeyEvent(event);
return true;
}
}
return super.onKeyPreIme(keyCode, event);
}
}
Then we override the abc_search_view
layout to use this above class. We use the original source code, only changing the EditText
class to our above-extended class. Create a layout file called abc_search_view.xml
Here is the code;
<?xml version="1.0" encoding="utf-8"?><!--
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- This is actually used for the badge icon *or* the badge label (or neither) -->
<TextView
android:id="@+id/search_badge"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginBottom="2dip"
android:drawablePadding="0dip"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone" />
<ImageView
android:id="@+id/search_button"
style="?attr/actionButtonStyle"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:contentDescription="@string/abc_searchview_description_search"
android:focusable="true" />
<LinearLayout
android:id="@+id/search_edit_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="8dip"
android:layout_marginRight="8dip"
android:layout_weight="1"
android:layoutDirection="locale"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_mag_icon"
style="@style/RtlOverlay.Widget.AppCompat.SearchView.MagIcon"
android:layout_width="@dimen/abc_dropdownitem_icon_width"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:visibility="gone" />
<!-- Inner layout contains the app icon, button(s) and EditText -->
<LinearLayout
android:id="@+id/search_plate"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal">
<view
android:id="@+id/search_src_text"
class="com.example.widget.search.MySearchViewSearchAutoComplete"
android:layout_width="0dp"
android:layout_height="36dip"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@null"
android:dropDownAnchor="@id/search_edit_frame"
android:dropDownHeight="wrap_content"
android:dropDownHorizontalOffset="0dip"
android:dropDownVerticalOffset="0dip"
android:ellipsize="end"
android:imeOptions="actionSearch"
android:inputType="text|textAutoComplete|textNoSuggestions"
android:paddingLeft="@dimen/abc_dropdownitem_text_padding_left"
android:paddingRight="@dimen/abc_dropdownitem_text_padding_right"
android:singleLine="true" />
<ImageView
android:id="@+id/search_close_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/abc_searchview_description_clear"
android:focusable="true"
android:paddingLeft="8dip"
android:paddingRight="8dip" />
</LinearLayout>
<LinearLayout
android:id="@+id/submit_area"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_go_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/abc_searchview_description_submit"
android:focusable="true"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:visibility="gone" />
<ImageView
android:id="@+id/search_voice_btn"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/abc_searchview_description_voice"
android:focusable="true"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
And that's it, it should work.
专注分享java语言的经验与见解,让所有开发者获益!
评论