gpt4 book ai didi

android - ListView 中有多个 EditText,点击聚焦一个 EditText,焦点跳转到第一个

转载 作者:搜寻专家 更新时间:2023-11-01 09:33:16 25 4
gpt4 key购买 nike

我在 ListView 的行中有 EditText。当我点击其中一个 EditText 时,会出现软键盘并且焦点会跳转到列表中的第一个 EditText,而不是停留在我点击的字段中。

这是一个视频:

https://youtu.be/ZwuFrX-WWBo

我创建了一个完全精简的应用程序来演示这个问题。完整代码在这里:https://pastebin.com/YT8rxqKa

我没有做任何事情来改变我代码中的焦点:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.cell_textfield, parent, false);
}

TextView label = (TextView) convertView.findViewById(R.id.textview1);
EditText textfield = (EditText) convertView.findViewById(R.id.textview2);

String text = String.format("Row %d", position);
label.setText(text);
textfield.setText(text);

return convertView;
}

我找到了 another post on StackOverflow为这种愚蠢的 Android 行为提供解决方法,其中涉及将 OnFocusChangedListener 放在所有文本字段上,以便在不正确地从中获取焦点时它们可以重新获得焦点。

这有助于重新获得焦点,但后来我发现当文本字段重新获得焦点时,光标最终会出现在文本的开头而不是结尾,这对我的用户来说是不自然和烦人的。

这是一个视频:

https://youtu.be/A35wLqbuIac

这是 OnFocusChangeListener 的代码。它可以解决 Android 移动焦点的愚蠢行为,但光标在重新获得焦点后会错位。

View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
long t = System.currentTimeMillis();
long delta = t - focusTime;
if (hasFocus) { // gained focus
if (delta > minDeltaForReFocus) {
focusTime = t;
focusTarget = view;
}
}
else { // lost focus
if (delta <= minDeltaForReFocus && view == focusTarget) {
focusTarget.post(new Runnable() { // reset focus to target
public void run() {
Log.d("BA", "requesting focus");
focusTarget.requestFocus();
}
});
}
}
}
};

我讨厌不得不在创可贴上贴创可贴,试图让 Android 的行为就像它自然预期的行为一样,但我会尽我所能。

1) 我可以做些什么来从源头上解决这个问题,而根本不需要 OnFocusChangeListener?

2) 如果 (1) 不可能,那么我如何确保当我强制将焦点返回到正确的字段时我确保光标位于末尾?我尝试在 requestFocus() 之后立即使用 setSelection(),但由于文本字段尚未聚焦,因此选择被忽略。

最佳答案

这是我的“解决方案”。简而言之:ListView 是愚蠢的,并且在涉及 EditText 时永远是一场噩梦,所以我更改了 fragment/适配器代码以适应ListView 布局或 ScrollView 布局。它仅在行数较少时才有效,因为 ScrollView 实现无法利用延迟加载和 View 回收。值得庆幸的是,在任何情况下我都希望在 ListView 中使用 EditText,我很少有超过 20 行左右。

在我的 BaseListFragment 中扩展我的 View 时,我通过依赖于 hasTextFields() 方法的方法获取布局 ID:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
return view;
}

public boolean hasTextfields() {
return false;
}

public int getLayoutId() {
if (hasTextfields()) {
return R.layout.scrollfragment;
} else {
return R.layout.listfragment;
}
}

在我的 BaseListFragment 的各个子类中,如果我需要在我的字段之一中使用 EditText,我只需覆盖 hasTextFields() 方法返回 true,然后我的 fragment/适配器切换到使用基本的 ScrollView 实现。

从那里开始,就是要确保适配器处理 ListViewScrollView 场景的标准 ListView 操作。像这样:

public void notifyDataSetChanged() {
// If scrollContainer is not null, that means we're in a ScrollView setup
if (this.scrollContainer != null) {
// intentionally not calling super
this.scrollContainer.removeAllViews();
this.setupRows();
} else {
// use the real ListView
super.notifyDataSetChanged();
}
}

public void setupRows() {
for (int i = 0; i < this.getCount(); i++) {
View view = this.getView(i, null, this.scrollContainer);
view.setOnClickListener(myItemClickListener);
this.scrollContainer.addView(view);
}
}

点击监听器出现的一个问题是 ListView 需要一个 AdapterView.OnItemClickListener,但是 ScrollView 中的任意 View 需要一个简单的 View.OnClickListener。因此,我让 ItemClickListener 也实现了 View.OnClickListener,然后将 OnClick 分派(dispatch)给 OnItemClick 方法:

public class MyItemClickListener implements AdapterView.OnItemClickListener, View.OnClickListener {

@Override
public void onClick(View v) {
// You can either have your Adapter set the tag on the View to be its position
// or you could have your click listener use v.getParent() and iterate through
// the children to find the position. I find its faster and easier to have my
// adapter set the Tag on the view.
int position = v.getTag();
this.onItemClick(null, v, config.getPosition(), 0);
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// ...
}
}

然后在 MyEditTextListFragment 中,我这样创建适配器:

listener = createClickListener();
adapter = createListAdapter();

if (scrollContainer != null) {
adapter.setScrollContainer(scrollContainer);
adapter.setMenuItemClickListener(listener);
adapter.setupRows();

} else {
getListView().setOnItemClickListener(listener);
getListView().setAdapter(adapter);
}

这是我的scrollfragment.xml 供引用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:clickable="true"
>

<!--
The following LinearLayout as a focus catcher that won't cause the keyboard to
show without it, the virtual keyboard shows up immediately/always which means we
never get to the enjoy the full size of our screen while scrolling, and
that sucks.
-->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>

<!--
This ListView is still included in the layout but set to visibility=gone. List
fragments require a standard ListView in the layout, so this gets us past that
check and allows us to use the same adapter code in both listview and scrollview
situations.
-->
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:background="@null"
android:layout_alignParentTop="true"
android:descendantFocusability="afterDescendants"

android:visibility="gone"
/>


<!--
This scrollview will act as our fake listview so that we don't have to deal with
all the stupid crap that comes along with having EditTexts inside a ListView.
-->
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="afterDescendants"
>

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

</LinearLayout>
</ScrollView>
</RelativeLayout>

关于android - ListView 中有多个 EditText,点击聚焦一个 EditText,焦点跳转到第一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45473046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com