2

Я реализовал ViewPager, который имеет разные фрагменты на каждой странице. В режиме портрета ViewPager отображает один фрагмент. В ландшафтном режиме ViewPager отображает два фрагмента бок о бок. Я достиг этого с помощью переопределения getPageWidth() в ViewPagerAdapter. Например:Два фрагмента ViewPager рядом не будут сфокусированы EditText

@Override 
public float getPageWidth(int position) { 
    DisplayMetrics metrics = getResources().getDisplayMetrics(); 
    if ((metrics.widthPixels/metrics.density) > 900) { 
     return (0.5f); 
    } 
    return super.getPageWidth(position); 
} 

В обоих фрагментах у меня есть поля EditText.

Когда в ландшафтном режиме и два фрагмента сидят бок о бок, я могу щелкнуть и выделить фокус на EditText на левом фрагменте. При попытке нажать EditText на правом фрагменте, я не могу и получить следующее предупреждение в моем журнале:

W/IInputConnectionWrapper: getTextBeforeCursor на неактивном InputConnection

MainActivity.java

public class MainActivity extends AppCompatActivity /*implements PageLoader*/ { 
    MyPagerAdapter adapter; 
    DirectionalViewPager pager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     // Get the ViewPager and set it's PagerAdapter so that it can display items 
     pager = (DirectionalViewPager) findViewById(R.id.vpPager); 
     adapter = new MyPagerAdapter(getSupportFragmentManager()); 
     pager.setOffscreenPageLimit(8); 
     pager.setAdapter(adapter); 
    } 

    public class MyPagerAdapter extends SmartFragmentStatePagerAdapter { 
     private static final int NUM_ITEMS = 4; 

     public MyPagerAdapter(FragmentManager fragmentManager) { 
      super(fragmentManager); 
     } 

     // Returns total number of pages 
     @Override 
     public int getCount() { 
      return NUM_ITEMS; 
     } 

     // Returns the fragment to display for that page 
     @Override 
     public Fragment getItem(int position) { 
      switch (position) { 
       case 0: // Fragment # 0 - This will show Frag1 
        return Frag1.newInstance(position, Frag1.class.getSimpleName()); 
       case 1: // Fragment # 0 - This will show Frag1 different title 
        return Frag1.newInstance(position, Frag1.class.getSimpleName()); 
       case 2: // Fragment # 1 - This will show Frag2 
        return Frag2.newInstance(position, Frag2.class.getSimpleName()); 
       default: 
        return Frag3.newInstance(position, Frag3.class.getSimpleName()); 
      } 
     } 

     // Returns the page title for the top indicator 
     @Override 
     public CharSequence getPageTitle(int position) { 
      return "Page " + position; 

     } 

     @Override 
     public float getPageWidth(int position) { 
      DisplayMetrics metrics = getResources().getDisplayMetrics(); 
      if ((metrics.widthPixels/metrics.density) > 900) { 
       return (0.5f); 
      } 
      return super.getPageWidth(position); 
     } 
    } 
} 

Frag1.java, Frag2.java и Frag3.java

public class Frag1 extends Fragment { 
    // newInstance constructor for creating fragment with arguments 
    public static Frag1 newInstance(int page, String title) { 
     Frag1 fragmentFirst = new Frag1(); 
     Bundle args = new Bundle(); 
     args.putInt("someInt", page); 
     args.putString("someTitle", title); 
     fragmentFirst.setArguments(args); 
     return fragmentFirst; 
    } 
    // Inflate the view for the fragment based on layout XML 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.frag1, container, false); 
     return view; 
    } 
} 

frag1.xml, frag2.xml и frag3.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" 
    android:background="#cc2"> 

    <TextView 
     android:id="@+id/txt_frag1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:text="txt_frag1" 
     /> 
    <Button 
     android:id="@+id/btn_frag1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center" 
     android:text="btn_frag1" 
     android:textSize="26dp" /> 

    <EditText 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/et_frag1" 
     android:ems="10" 
     android:text="ET_FRAG1"/> 

</LinearLayout> 

Почему это происходит и как я могу получить вокруг него?

+0

вам следует скрыть клавиатуру вручную и показать снова, когда вы переключаете Editext. – Herry

+0

Нет, это не работает. Я попытался спрятать клавиатуру OnFocusChange и показать ее снова, когда пользователь нажимает на текст редактирования. Но EditText справа отказывается фокусироваться. Я даже пытался v.requestFocus() в событии OnClick. – chaser

+0

попробуйте использовать getChildFragmentManager() вместо getSupportFragmentManager() –

ответ

2

После бесчисленных часов, прочесывающих интернет, я нашел это SO answer, что объясняет, что эта проблема является врожденной проблемой ViewPager. Поэтому единственный способ по-настоящему исправить это - изменить сам источник ViewPager.

void populate(int newCurrentItem) { 

    // ... CODES OMITTED 

    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) { 
    float curItemOffset = mCurItem * info.widthFactor; // find the offset value for curr item 
    float offsetUpperBound = curItemOffset + 1;   // +1 to get the upper bound offset value 
    if ((info.offset >= curItemOffset) && (info.offset < offsetUpperBound)) 
     return true; // curr item offset value is within bound, hence it is on the screen 
    return false; 
} 

Пожалуйста вверх-голосования тот или другой SO ответ, если вы найдете это полезным, потому что это было очень трудно выкопать из-за непопулярности этой проблемы. Хотя я не понимаю, почему было бы интересно, что ViewPager сам популярен, поэтому наверняка люди раньше использовали EditText (возможно, их не так много используют на нескольких страницах на одном экране)

Смежные вопросы