android 多个edittext焦点,关于android:ListView中有多个EditText,点击以将焦点放在一个EditText上,焦点将跳转到第一个...

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

这是一个视频:

我创建了一个完全精简的应用程序来演示该问题。完整的代码在这里: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;

}

我在StackOverflow上找到了另一篇文章,提供了针对这种愚蠢的Android行为的解决方法,该方法涉及在所有文本字段上放置OnFocusChangedListener,以便在不正确地将其取回时可以重新获得焦点。

这样做可以重新获得焦点,但是后来我发现,当文本字段重新获得焦点时,光标最终停留在文本的开头而不是结尾,这对我的用户来说是不自然的且令人讨厌的事情。

这是一个视频:

这是该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(),但是由于文本字段尚未聚焦,因此选择被忽略。

您对此有很好的解决方案吗? 我现在有同样的问题。

@SreeramSunkara我没有很好的解决方法,但是我确实找到了行之有效的方法。 简而言之,当我需要一个带有EditTexts的ListView时,我将只使用基本的ScrollView。 只要您没有太多的行,它就可以很好地工作。 实际上,我的适配器代码工作得足够好,以至于我完全被欺骗了,并且我的布局实际上没有ListView。 在进行新项目时,我再次发现了这个问题,不得不深入研究旧代码以弄清楚我是如何解决的。 虐待尝试在下面发布示例答案。

这是我的"解决方案"。简而言之:ListView是愚蠢的,并且在涉及到EditText时始终是一个噩梦,所以我更改了Fragment / Adapter代码以使其能够适应ListView布局或ScrollView布局。它仅在行数较少的情况下才有效,因为scrollview实现无法利用延迟加载和视图回收的优势。幸运的是,在任何情况下我想要在ListView中使用EditTexts的情况下,我很少有超过20行左右。

在BaseListFragment中扩大视图时,我通过依赖于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,然后我的片段/适配器切换为使用基本的scrollview实现。

从那里开始,要确保适配器能够处理ListView和ScrollView场景的标准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调度到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供参考:

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"

>

android:focusable="true"

android:focusableInTouchMode="true"

android:layout_width="0px"

android:layout_height="0px"/>

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"

/>

android:id="@+id/scrollView"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:descendantFocusability="afterDescendants"

>

android:id="@+id/scrollContainer"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical"

>

尝试一次,对我有用:

public void setCursorPosition() {

focusTarget.requestFocus();

focusTarget.setCursorVisible(true);

other.setCursorVisible(false);

} else {

other.setCursorVisible(true);

focusTarget.setCursorVisible(false);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值