android / views-widgets-samples

Multiple samples showing the best practices in views-widgets on Android.
Apache License 2.0
5.04k stars 3.01k forks source link

Focus issue with EditTexts in Fragments when using ViewPager2 #107

Open raranov opened 4 years ago

raranov commented 4 years ago

Build: AI-191.8026.42.35.6010548, 201911150702,

AI-191.8026.42.35.6010548, JRE 1.8.0_202-release-1483-b03x64 JetBrains s.r.o, OS Windows 10(amd64) v10.0 , screens 1536x864

AS: 3.5.3; Android Gradle Plugin: 3.5.3; Gradle: 5.4.1; NDK: from local.properties: (not specified), latest from SDK: (not found); LLDB: pinned revision 3.1 not found, latest from SDK: (package not found); CMake: from local.properties: (not specified), latest from SDK: (not found), from PATH: (not found)

I have an activity with a ViewPager2 container that swaps between three fragments. Each fragment contains two EditTexts. I have disabled manual scrolling, and the user can only traverse the fragments via a continue button. The goal is for the app to automatically focus the first EditText on the screen when the user opens that screen. The issue is that instead of the EditText getting focus, the ViewPager itself is getting the focus, even though it is not focusable. To try to fix this issue, I tried having the edittext explicitly requestFocus() in the fragment itself, but this doesn't help (after the user presses continue on the first screen, he gets to the second screen and the first edittext has no cursor or focus) and leads to some interesting scrolling issues. When I debug, I see that the ViewPager container itself has the focus.

Here is the repo, it is the ViewPager2 bug branch: https://github.com/raranov/MyExperienceNew/tree/ViewPager2 ViewPager (1) does not have this issue.

Also, I tried to do a similar thing using straight recyclerview, and that also had similar focus issues. The details are here: https://stackoverflow.com/questions/59489756/issue-with-focus-behavior-when-using-edittexts-in-a-recyclerview

Thank you.

CakeWalker1337 commented 4 years ago

I have also struggled with this issue! I used viewpager 1 to avoid that bug in my project. Here is a test project which reproduces this bug: https://github.com/CakeWalker1337/ViewPager2-bugreport It would be great, if you fix it:)

shadabunique commented 4 years ago

I have to use ViewPager2 in order to support Arabic locale as well. Is somebody looking into this issue?

VyacheslavMartynenko commented 4 years ago

I have a similar problem when I use ViewPager2 with FragmentStateAdapter. When I do navigation first time on a fragment by setCurrentItem, I can focus on an EditText. But reselecting the fragment causes the issue. You need to tap on the EditText twice because the first tap won't focus on the field, but you can still input message from the keyboard.

In this situation, as a temporary solution, I can set offscreen page limit to 1. Still expecting a normal fix.

HarunJr commented 4 years ago

Experiencing the same issue moving from fragment to fragment with edittext

FEvgenSON commented 4 years ago

Same on view holder

samgithiaka commented 4 years ago

I have the same issue and i have to use viewpager2 for vertical scroll which is not supported in viewpager1

Nikunj2505 commented 3 years ago

Same issue when using edit text with fragments with viewpager2. Is there any work around?

FEvgenSON commented 3 years ago

Increase offscreen page limit

schlagi123 commented 3 years ago

I have the same issue.

Thanks to @FEvgenSON for the workaround, but I hope it will be fixed

Ifans007 commented 3 years ago

Unfortunately increase offscreen page limit don't work for me

Ifans007 commented 3 years ago

In my case the number of offscreenPageLimit should be not smaller the number of pages

FeatherSeven commented 3 years ago

There are 3 workarounds for this issue, all worked in my case:

  1. increase offsetScreenPageLimit, 1 is enough no matter how many pages i got;
  2. vp2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
  3. ((RecyclerView)vp2.getChildAt(0)).getLayoutManager().setItemPrefetchEnabled(false);
PembaTamang commented 2 years ago

Same issue here, is there a fix available ?

PembaTamang commented 2 years ago

There are 3 workarounds for this issue, all worked in my case:

  1. increase offsetScreenPageLimit, 1 is enough no matter how many pages i got;
  2. vp2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
  3. ((RecyclerView)vp2.getChildAt(0)).getLayoutManager().setItemPrefetchEnabled(false);

this didn't work for me

KitsuneFolk commented 1 year ago

Same issue here, is there a fix available ?

Hey, we solved this bug in the library called Fragula. I found out that transferring the ViewPager2 code to the project and commenting out the dispatchSelected method in the ScrollEventAdapter class solves it. If you're okay with transferring the library to your app, you might use this solution to fix the bug. Here's the commit: https://github.com/massivemadness/Fragula/pull/23/commits/61aca39074322cb24d0a44fc5cbed42657b36eea"

OoadaioO commented 1 year ago
  1. when editText is child of viewpager2,may try this
fun ViewPager2.setDescendantFocusabilityKtx(focusability:Int) {
    if (childCount > 0) {
        val rl = this.getChildAt(0)
        if (rl is RecyclerView) {
            rl.descendantFocusability = focusability
        }
    }
}

binding.viewPager.setDescendantFocusabilityKtx(ViewGroup.FOCUS_AFTER_DESCENDANTS)

2. when edittext is slibing node of viewpager2

fun ViewPager2.setIsFocusableInTouchModeKtx(isFocusableInTouchMode:Boolean){
    if (childCount > 0) {
        val rl = this.getChildAt(0)
        if (rl is RecyclerView) {
            rl.isFocusableInTouchMode = isFocusableInTouchMode
        }
    }
}
binding.viewPager. setIsFocusableInTouchModeKtx(false)
zhuhuan0122 commented 9 months ago

Has ViewPager2 called the setPageTransformer() method? Please check if there are any issues with the overridden ViewPager2.PageTransformer. For example, like in the code below, does it require setVisibility(View.GONE)?

private const val MAX_ROTATION = 10.0f

class RotatePageTransformer : ViewPager2.PageTransformer {

override fun transformPage(page: View, position: Float) {
    page.apply {
        when {
            position <= 0 -> {
                setViewVisible()
                alpha = 1f
                pivotX = width / 2f
                pivotY = height * 1f
                rotation = position * MAX_ROTATION
                translationX = 0f
            }
            position <= 1 -> {
                alpha = if (position == 1f) {
                    //need gone
                    setViewGone()
                    0f
                } else {
                    setViewVisible()
                    (1 - position).coerceAtLeast(0.35f)
                }
                rotation = 0f
                translationX = -position * page.width
            }
            else -> {
                setViewVisible()
                alpha = 0f
                rotation = 0f
                translationX = 0f
            }
        }
    }
}

}