Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Viewpager2 fragment freezes custom spinner widget when returned after swiping #140

Open
zia4mobileapp opened this issue Jul 28, 2020 · 2 comments

Comments

@zia4mobileapp
Copy link

I am using a custom material spinner from this library.

So here is the problem when using a Viewpager2(implementation "androidx.viewpager2:viewpager2:1.0.0") in fragments.

Each fragment consists of an TextInputEditText inside a TextInputLayout.

I have 3 fragments and all the 3 have this custom spinner inside, when navigating to third fragment(by swiping) and returning back to the first fragment the Material Spinner freezes that is on clicking it, does not show the items, the onClick freezes. It enables only when the text field in that layout is focussed and the keyboard pop's up.

Steps to reproduce,
Here is the code for the ViewPager2 and those 3 fragments,

public class MainActivity extends AppCompatActivity {
    ActivityMainBinding activityMainBinding;
    ViewPager2Adapter mViewPager2Adapter;
    public static String TAG = MainActivity.class.getSimpleName();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);       
        mViewPager2Adapter=new ViewPager2Adapter(this);
        mViewPager2Adapter.addFragment(FragmentOne.newInstance(),"One");
        mViewPager2Adapter.addFragment(FragmentTwo.newInstance(),"Two");
        mViewPager2Adapter.addFragment(FragmentThree.newInstance(),"Other ");
        activityMainBinding.viewPager2.setAdapter(mViewPager2Adapter);
    }   
    }

Inside FragmentOne,the same is for rest of the fragments

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        viewBinding= DataBindingUtil.inflate(inflater,
                R.layout.fragment_one, container, false);

         viewBinding.matSpinOne.setItems(getItems());
        viewBinding.matSpinTwo.setAdapter(getItems());
        viewBinding.matSpinThree.setItems(getItems());

        return viewBinding.getRoot();
    }

public ArrayList<String> getItems()
    {

        ArrayList<String> itemList=new ArrayList<>();
        itemList.add("Android OS");
        itemList.add("Windows");
        itemList.add("Linux ");
        itemList.add("ios");
        itemList.add("Mac OS");
        itemList.add("Debian");

        return itemList;
    }

FragmentOne layout XML

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:clickable="true"
        android:focusable="true"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        >

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >
                <TextView
                  android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="14sp"
                   android:layout_margin="10dp"   
                    android:text="One Spinner"
                    />
                <com.jaredrummler.materialspinner.MaterialSpinner
                    android:id="@+id/matSpinOne"
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    />
                <TextView
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="14sp"
                   android:layout_margin="10dp"   
                    android:text="Two Spinner"
                    />

                <com.jaredrummler.materialspinner.MaterialSpinner
                    android:id="@+id/matSpinTwo"
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    />
                    
                    
                     <TextView
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="14sp"
                   android:layout_margin="10dp"   
                    android:text="Three Spinner"
                    />

                <com.jaredrummler.materialspinner.MaterialSpinner
                    android:id="@+id/matSpinThree"
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    />


                <com.google.android.material.textfield.TextInputLayout                   
                   android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="Text Layout 1"
                    >

                    <com.google.android.material.textfield.TextInputEditText                     
                         android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                        />

                </com.google.android.material.textfield.TextInputLayout>
            </LinearLayout>
        </ScrollView>
    </FrameLayout>

ViewPager Adapter code,

public class ViewPager2Adapter extends FragmentStateAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPager2Adapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getItemCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

}

I am using a custom material spinner from this library.

So here is the problem when using a Viewpager2(implementation "androidx.viewpager2:viewpager2:1.0.0") in fragments.

Each fragment consists of an TextInputEditText inside a TextInputLayout.

I have 3 fragments and all the 3 have this custom spinner inside, when navigating to third fragment(by swiping) and returning back to the first fragment the Material Spinner freezes that is on clicking it, does not show the items, the onClick freezes. It enables only when the text field in that layout is focussed and the keyboard pop's up.

Here is the code for the ViewPager2 and those 3 fragments,

public class MainActivity extends AppCompatActivity {
ActivityMainBinding activityMainBinding;
ViewPager2Adapter mViewPager2Adapter;
public static String TAG = MainActivity.class.getSimpleName();
@OverRide
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mViewPager2Adapter=new ViewPager2Adapter(this);
mViewPager2Adapter.addFragment(FragmentOne.newInstance(),"One");
mViewPager2Adapter.addFragment(FragmentTwo.newInstance(),"Two");
mViewPager2Adapter.addFragment(FragmentThree.newInstance(),"Other ");
activityMainBinding.viewPager2.setAdapter(mViewPager2Adapter);
}
}
Inside FragmentOne,the same is for rest of the fragments

@OverRide
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
viewBinding= DataBindingUtil.inflate(inflater,
R.layout.fragment_one, container, false);

     viewBinding.matSpinOne.setItems(getItems());
    viewBinding.matSpinTwo.setAdapter(getItems());
    viewBinding.matSpinThree.setItems(getItems());

    return viewBinding.getRoot();
}

public ArrayList getItems()
{

    ArrayList<String> itemList=new ArrayList<>();
    itemList.add("Android OS");
    itemList.add("Windows");
    itemList.add("Linux ");
    itemList.add("ios");
    itemList.add("Mac OS");
    itemList.add("Debian");

    return itemList;
}

FragmentOne layout XML

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            >
            <TextView
              android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp"
               android:layout_margin="10dp"   
                android:text="One Spinner"
                />
            <com.jaredrummler.materialspinner.MaterialSpinner
                android:id="@+id/matSpinOne"
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />
            <TextView
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp"
               android:layout_margin="10dp"   
                android:text="Two Spinner"
                />

            <com.jaredrummler.materialspinner.MaterialSpinner
                android:id="@+id/matSpinTwo"
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />
                
                
                 <TextView
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp"
               android:layout_margin="10dp"   
                android:text="Three Spinner"
                />

            <com.jaredrummler.materialspinner.MaterialSpinner
                android:id="@+id/matSpinThree"
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />


            <com.google.android.material.textfield.TextInputLayout                   
               android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Text Layout 1"
                >

                <com.google.android.material.textfield.TextInputEditText                     
                     android:layout_width="match_parent"
                android:layout_height="wrap_content"
                    />

            </com.google.android.material.textfield.TextInputLayout>
        </LinearLayout>
    </ScrollView>
</FrameLayout>

ViewPager Adapter code,

public class ViewPager2Adapter extends FragmentStateAdapter {

private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();

public ViewPager2Adapter(@NonNull FragmentActivity fragmentActivity) {
    super(fragmentActivity);
}

@NonNull
@Override
public Fragment createFragment(int position) {
    return mFragmentList.get(position);
}

@Override
public int getItemCount() {
    return mFragmentList.size();
}

public void addFragment(Fragment fragment, String title) {
    mFragmentList.add(fragment);
    mFragmentTitleList.add(title);
}

}
Here are my observations, when the viewpager is first displayed this line of code inside MaterialSpinner.java,

Line no 524: isLaidOut() returns true, when you swipe back to the third fragment and then come to first the isLaidOut() returns false which freezes the widget why does it return false if it has been laid already ???

The whole problem is with these lines,


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      isLaidOut = isLaidOut();
    } else {
      isLaidOut = getWidth() > 0 && getHeight() > 0;
    }

My Questions

If the View has already laid out once in the fragment why does isLaidOut() return false when the fragment's view is re-created in the ViewPager2 ?

Can I go ahead and just use isLaidOut = getWidth() > 0 && getHeight() > 0; this condition for devices above Lollipop ? (Not sure why that function was for)

Also posted here ,https://stackoverflow.com/questions/63128658/viewpager2-fragment-freezes-custom-spinner-widget-when-returned-after-swiping

@ghost
Copy link

ghost commented Nov 30, 2020

hello @zia4mobileapp have you found any solution for this bug in this library???

1 similar comment
@MostafaGad1911
Copy link

hello @zia4mobileapp have you found any solution for this bug in this library???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants