当使用具有所有默认设置的Spinner
时,我在使用S笔时发现了一些奇怪的错误:
- 如果打开微调器并将S笔悬停在列表底部,使其滚动到底部,然后向上提起S笔(使"悬停圆"消失(,则列表会跳回到顶部
- 如果打开微调器并将S笔悬停在列表底部,使其滚动到底部,然后选择一个选项,有时(间歇性地-可能是四分之一(它会忽略所选选项,然后跳回顶部
我正在横向测试平板电脑设备,该设备运行的是Android 9,但我在其他设备上做了一些测试,看起来是一样的。
相比之下,我尝试使用一个我经常使用的应用程序,该应用程序大量使用微调器——";装箱单";由dotnetideas。此应用程序上次更新于2019年,目标SDK为27。您可以通过进入设置并添加多个行李项目,然后尝试编辑任何装箱单项目上的行李,轻松测试应用程序中的微调器。我发现S Pen可以很好地与这个应用程序配合使用,而且它没有上面描述的错误,所以必须有一些方法来解决它。这不是一个开源应用程序,所以我无法从它们的源代码中获得想法。我尝试将目标SDK更改为27,但没有任何区别。
这是我的代码,在我看来,这是一个具有所有默认设置的微调器的完全普通的实现,并且仍然具有相同的";S笔错误";其在装箱单中不可重复。
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.penpoc">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SPenControlExperiment">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, MainFragment.newInstance())
.commitNow();
}
}
}
main_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
MainFragment.java:
public class MainFragment extends Fragment {
public static MainFragment newInstance() {
return new MainFragment();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.main_fragment, container, false);
Spinner spDefault = root.findViewById(R.id.spDefault);
ArrayAdapter<String> defaultSpinnerAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item);
defaultSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spDefault.setAdapter(defaultSpinnerAdapter);
defaultSpinnerAdapter.addAll(getExampleList());
defaultSpinnerAdapter.notifyDataSetChanged();
return root;
}
private List<String> getExampleList() {
List<String> list = new ArrayList<>();
list.add("Alpha");
list.add("Bravo");
list.add("Charlie");
list.add("Delta");
list.add("Echo");
list.add("Foxtrot");
list.add("Golf");
list.add("Hotel");
list.add("India");
list.add("Juliet");
list.add("Kilo");
list.add("Lima");
list.add("Mike");
list.add("November");
list.add("Oscar");
list.add("Papa");
list.add("Quebec");
list.add("Romeo");
return list;
}
}
main_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainFragment">
<!-- Add some text views to push the spinner further down the page, this is not strictly necessary -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="one" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="two" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="three" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="four" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="five" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="six" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="seven" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="eight" />
<Spinner
android:layout_width="350dp"
android:layout_height="wrap_content"
android:id="@+id/spDefault" />
</LinearLayout>
渐变deps:
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
我在S笔上也遇到了同样的问题。对于一个旧的应用程序,API 25Spinner
工作得很好,但API 30不再工作了。我能解决这个问题的唯一方法是用AutoCompleteTextView
s替换Spinner
s。它生成的下拉列表似乎可以正确地使用s笔。
需要进行一些调整,使其看起来像Spinner
:
1.使AutoCompleteTextView
不可编辑
从文档中,您可以通过添加android:inputType="none"
来实现它。但是,正如MaterialAutoCompleteTextView
代码中所说:
// Due to a framework bug, setting android:inputType="none" on xml has no effect. Therefore,
// we check it here in case the autoCompleteTextView should be non-editable.
所以你有两个选择:
- 以编程方式设置输入类型
autoComplete.setInputType(InputType.TYPE_NULL)
- 使用具有解决方法的
MaterialAutoCompleteTextView
2.句柄单击可显示下拉列表
AutoCompleteTextView
的默认行为是通过键入几个字符来显示建议。所以,当视线聚焦时,你必须强制进行下拉显示。
autoComplete.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
autoComplete.showDropDown();
}
}
});
autoComplete.setOnDismissListener(new AutoCompleteTextView.OnDismissListener() {
@Override
void onDismiss() {
// Force focus change after selection
autoComplete.clearFocus()
}
});
3.设置下拉列表的样式
与Spinner
从Adapter
同时调用getView()
和getDropDownView()
相反,AutoCompleteTextView
只调用getView()
。因此,为了提供正确的视图,您需要检查getView()
调用中的父类型:
@Override
public @NonNull View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
// Workaround for AutoCompleteTextView using only this method
if (parent instanceof ListView) {
return getDropDownView(position, convertView, parent);
} else {
return super.getView(position, convertView, parent);
}
}
4.设计AutoCompleteTextView
的样式
最后一件事是在AutoCompleteTextView
的末尾添加一个小插入符号,使其看起来像Spinner
。您可以使用XML布局文件中的android:drawableEnd
属性来处理此问题。
5.其他提示
AutoCompleteTextView
下拉列表选择触发AdapterView.OnItemClickListener
,而不是像Spinner
那样触发AdapterView.OnItemSelectedListener
。方法签名几乎相同- 没有合适的方法来为初始值触发此侦听器。作为一种变通方法,您可以设置初始值,然后附加监听器,并将您的第一个验证逻辑放入其构造函数中