Android: EditText focus jumps to another inside ScrollView(Android:EditText焦点跳转到ScrollView中的另一个)
问题描述
我有多个使用 ViewPager 水平相邻的片段.每个片段都有一个 ScrollView,其中包含一个带有许多 EditText 视图的表.当我单击 EditText 时,它获得焦点,然后将其丢失给最左侧片段中的其他一些 EditText.有时焦点切换会立即发生,有时在我输入 EditText 时会发生.通常,最左侧片段中最顶部的 EditText 会抢占焦点.
I have multiple fragments horizontally adjacent using a ViewPager. Each fragment has a ScrollView that contains a table with many EditText views. When I click on a EditText, it gains focus and then loses it to some other EditText in the leftmost fragment. Sometimes the focus switch happens immediately, sometimes while I am typing into a EditText. Usually, the topmost EditText in the leftmost fragment steals focus.
单击最左侧片段中的 EditText 时,我看不到问题,即使它不是最顶部的片段.它就像 Android 不喜欢关注不在左边缘的 TextView.这听起来很熟悉吗?
I don't see the problem when a EditText in the leftmost fragment is clicked, even if it is not the topmost one. Its like Android doesn't like focusing on a TextView that is not along the left edge. Does this sound familiar?
按照 Skip 在 randomly- 中的建议,我尝试覆盖 ScrollView 中的 findFocus() 方法,但未成功跳跃.附上的源代码很大,但可能对其他人有用...
I have unsuccessfully tried overriding the findFocus() method in ScrollView as suggested by Skip in randomly-jumping. The source code attached is huge, but it may be useful to others...
package com.example.slideViewPager;
import java.util.ArrayList;
import com.example.slideViewPager.R;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class SlideViewPager extends FragmentActivity {
private static Context g;
private static ArrayList<String> pages;
private static int currentItem; // restore page position after tilt
private static int[] scrollStateY;
private static NotesViewFragment[] fragmentArray;
private static int id; // to create unique view ids
@Override
public void onCreate(Bundle savedInstanceState) {
g = getApplicationContext();
setContentView(R.layout.activity_slide_view_pager);
pages = new ArrayList<String>();
for (int i = 0; i < 4; ++i)
pages.add(Integer.toString(i));
if (savedInstanceState == null) {
currentItem = 0;
scrollStateY = new int[pages.size()]; // assume all 0s
id = 0;
}
else {
currentItem = savedInstanceState.getInt("currentItem");
scrollStateY = savedInstanceState.getIntArray("scrollStateY");
id = savedInstanceState.getInt("id");
System.out.println("Notes onCreate RESTORE: currentItem="+currentItem+"; id="+id);
}
fragmentArray = new NotesViewFragment[pages.size()];
System.out.println("onCreate: start");
super.onCreate(savedInstanceState);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
NotesPagerAdapter pagerAdapter = new NotesPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(pagerAdapter);
viewPager.setCurrentItem(currentItem);
viewPager.setOnPageChangeListener(onPageChangeListener);
System.out.println("onCreate: done");
}
@Override
public void onSaveInstanceState(Bundle bundle) {
System.out.println("Notes: onSaveInstanceState: currentItem="+currentItem);
super.onSaveInstanceState(bundle);
bundle.putInt("currentItem", currentItem);
bundle.putIntArray("scrollStateY", scrollStateY);
bundle.putInt("id", id);
}
public void onBackPressed() {
System.out.println("Notes: onBackPressed: currentItem="+currentItem);
super.onBackPressed();
}
/////////////////////////////////////////////////////////////////
public static class NotesPagerAdapter extends FragmentPagerAdapter {
public NotesPagerAdapter(FragmentManager fm) {
super(fm);
System.out.println("NotesPagerAdapter: this="+this);
}
@Override
public Fragment getItem(int position) {
String pageNum = pages.get(position);
NotesViewFragment notesViewFragment = NotesViewFragment.initialize(pageNum, position); // create new fragment
System.out.println("NotesPagerAdapter: getItem: CREATED position:"+position+" = page:"+pageNum+"; fragment="+notesViewFragment);
return notesViewFragment;
}
@Override
public int getCount() {
return pages.size();
}
// nothing being done here
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
System.out.println("NotesPagerAdapter: destroyItem position="+position);
super.destroyItem(container, position, object);
}
@Override
public float getPageWidth(int position) {
System.out.println("NotesPagerAdapter: getPageWidth position="+position);
return (1.0f/2); // vary # pages/view
}
}
//////////////////////////////////////////////////////
public static class NotesViewFragment extends Fragment {
private int position; // needed to save scrollY into scrollStateY[]
private String pageNum; // index
private ScrollView itemScrollView;
public NotesViewFragment() {
super();
System.out.println("NotesViewFragment: new this:"+this);
}
public static NotesViewFragment initialize(String page, int position) {
NotesViewFragment notesViewFragment = new NotesViewFragment();
System.out.println("NotesViewFragment: initialize: this:"+notesViewFragment+"; page: "+page+"; position="+position);
Bundle args = new Bundle();
args.putString("pageNum", page);
args.putInt("position", position);
scrollStateY[position] = 0; // start at top
notesViewFragment.setArguments(args);
return notesViewFragment;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
System.out.println("NotesViewFragment: onSaveInstanceState this:"+this+"; page: "+pageNum+"; scrollView="+itemScrollView);
// itemScrollView will be null occasionally (attached but not createViewed)
if (itemScrollView != null)
scrollStateY[position] = itemScrollView.getScrollY();
outState.putString("pageNum", pageNum);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
pageNum = args.getString("pageNum");
position = args.getInt("position");
fragmentArray[position] = this;
System.out.println("NotesViewFragment: onCreate: this:"+this+"; page: "+pageNum+"; position="+position+"; yPos="+scrollStateY[position]);
}
else // should not happen
System.out.println("NotesViewFragment: onCreate: NO ARGS !!! this:"+this);
}
public void onDestroyView() {
super.onDestroyView();
if (itemScrollView != null) // could be null if not createViewed
scrollStateY[position] = itemScrollView.getScrollY();
System.out.println("NotesViewFragment: onDestroyView: "+pageNum+" this="+this+"; scrollY="+scrollStateY[position]);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (savedInstanceState != null) { // config change happened
pageNum = savedInstanceState.getString("pageNum");
System.out.println("NotesViewFragment: onCreateView: RESTORED "+pageNum+" this="+this+"; yPos="+scrollStateY[position]);
}
else
System.out.println("NotesViewFragment: onCreateView: "+pageNum+"; this="+this);
// Inflate the layout containing a title and body text.
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_screen_slide_page, container, false);
TableLayout itemNotesTable = (TableLayout) rootView.findViewById(R.id.tableLayoutNotes);
TextView itemTitle = (TextView) rootView.findViewById(R.id.textViewTitle);
itemScrollView = (ScrollView) rootView.findViewById(R.id.scroll_form);
itemTitle.setText("Team "+pageNum);
for (int i = 0; i < 12; ++i) {
TableRow tr = new TableRow(g);
tr.setId(++id);
ImageView itemThumbnail = new ImageView(g);
itemThumbnail.setId(++id);
itemThumbnail.setImageResource(R.drawable.notes); // set icon
tr.addView(itemThumbnail);
LinearLayout ll = new LinearLayout(g);
ll.setId(++id);
ll.setOrientation(LinearLayout.VERTICAL);
String text = " Team "+pageNum;
ll.addView(makeTextItem(text, false));
TextView textView;
if ((id % 2) == 0) { // make some entries editable
textView = new EditText(g);
textView.setFocusable(true);
textView.setFocusableInTouchMode(true);
textView.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
textView.setOnFocusChangeListener(onFocusChangeListener);
}
else
textView = new TextView(g);
textView.setId(++id);
String str = "Line "+i+" is blah blah blah and more blah blah blah";
textView.setText(str);
textView.setTextColor(Color.BLACK);
textView.setTextSize(16);
textView.setPadding(2, 2, 2, 2); // start, top, end, bottom
ll.addView(textView);
tr.addView(ll);
itemNotesTable.addView(tr);
tr.setOnClickListener(noteClicked); // make everything in table row clickable
}
if (scrollStateY[position] != 0) {
itemScrollView.post(new Runnable() {
public void run() {
itemScrollView.scrollTo(0, scrollStateY[position]);
}
});
}
return rootView;
}
// called from fillNotes
private static TextView makeTextItem(String label, boolean bold) {
TextView item = new TextView(g);
item.setId(++id);
item.setText(label);
item.setTextColor(Color.BLACK);
item.setTextSize(16);
if (bold)
item.setTypeface(null, Typeface.BOLD);
return item;
}
}
// listens for horizontal page scrolls
ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
System.out.println("onPageChangeListener: leaving page:"+currentItem+"; for page: "+position);
currentItem = position;
}
};
static View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
System.out.println("onFocusChangeListener: "+hasFocus+"; "+view);
if (! hasFocus) {
EditText editText = (EditText) view;
String text = editText.getText().toString();
System.out.println("onFocusChangeListener: "+text);
}
}
};
static OnClickListener noteClicked = new OnClickListener() {
public void onClick(View tr) {
for (View parent = tr; parent != null; parent = (View) parent.getParent()) {
for (NotesViewFragment fragment : fragmentArray)
if (fragment != null && fragment.itemScrollView == parent) {
System.out.println("noteClicked: page: "+fragment.pageNum);
return;
}
}
}
};
}
有几个 XML 文件:fragment_screen_slide_page.xml ..........
There are a couple of XML files: fragment_screen_slide_page.xml ..........
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textViewTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text=""
android:textAppearance="?android:attr/textAppearanceLarge" />
<View
android:id="@+id/separator"
android:layout_width="fill_parent"
android:layout_height="1dip"
android:layout_alignParentRight="true"
android:layout_marginTop="4dp"
android:layout_below="@+id/textViewTitle"
android:background="#888888" />
<ScrollView
android:id="@+id/scroll_form"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/separator" >
<TableLayout
android:id="@+id/tableLayoutNotes"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="1" >
</TableLayout>
</ScrollView>
</RelativeLayout>
和activity_slide_view_pager.xml ----------
and activity_slide_view_pager.xml ----------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"
tools:context=".Page" >
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
推荐答案
焦点正在更改到最左边的片段,因为该片段是 ViewPager
的当前项.您可以尝试使用 setCurrentItem(item)
将当前项目设置为另一个片段(当用户单击它时),这样左边的项目就不会窃取焦点.
Focus is changing to the leftmost fragment because that fragment is the current item of the ViewPager
. You might try to use setCurrentItem(item)
to set the current item to the other fragment (when the user clicks on it) so the left one doesn't steal focus.
发生这种情况是因为在 ViewPager
的 populate()
函数结束时,它总是将焦点放在当前项目中的视图上.您还可以通过复制 ViewPager
源并更改此代码以允许屏幕让孩子专注.
This is happening because at the end of the populate()
function of the ViewPager
it will always give focus to a view that is in the current item. You could also fix this issue by copying the ViewPager
source and changing this code to allow any fragment which is on the
screen to have a child with focus.
改变这个:
if (hasFocus()) {
View currentFocused = findFocus();
ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
if (ii == null || ii.position != mCurItem) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
ii = infoForChild(child);
if (ii != null && ii.position == mCurItem) {
if (child.requestFocus(FOCUS_FORWARD)) {
break;
}
}
}
}
}
这样的:
if (hasFocus()) {
View currentFocused = findFocus();
ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused) : null;
if (ii == null || !infoIsOnScreen(ii)) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
ii = infoForChild(child);
if (ii != null && infoIsOnScreen(ii)) {
if (child.requestFocus(FOCUS_FORWARD)) {
break;
}
}
}
}
}
public boolean infoIsOnScreen(ItemInfo info) {
// Code to determine if the view is on the screen using ii.offset etc.
}
这篇关于Android:EditText焦点跳转到ScrollView中的另一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Android:EditText焦点跳转到ScrollView中的另一个
基础教程推荐
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01