如何在移除片段时动态更新ViewPager

huangapple 未分类评论44阅读模式
标题翻译

How to update ViewPager dynamically when removing fragment

问题

I'm sorry a question that has already been answered in this web, but I can't find same case with mine.

I call lists of multiple columns from `RoomDatabase` for `SetText` in a `ViewPager`, and my question is how to dynamically update `ViewPager` when I delete record. In other questions I've checked, there was a single `TextView` in a `ViewPager`. But in my case, I assign arrays, that I received through bundle, into each `TextView` in `ArrayListFragment` class.

It's so frustrating after searching for what to do after `myAdapter.notifyDataSetChanged()` in delete button.

I will really appreciate your help.


public class FragmentStateLibraryPagerSupport extends Fragment {

    MyAdapter myAdapter;
    ViewPager mPager;
    public List<String> head_array;
    public List<String> desc_array;
    TodoDatabase db;

    @Nullable
    @Override
    public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.fragment_pager, null);
        Button btn_delete = root.findViewById(R.id.btn_delete);
        btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayListFragment arrayListFragment = new ArrayListFragment();
                String head_array_text = head_array.get(arrayListFragment.return_mNum());
                Log.e("head_array_text ::",  head_array.get(arrayListFragment.return_mNum()));

                TodoDatabase db = Room.databaseBuilder(getContext(), TodoDatabase.class, "todo-db").allowMainThreadQueries().build();
                db.todoDao().deleteRecord(head_array_text);
                myAdapter.notifyDataSetChanged();
            }
        });
        return root;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        db = Room.databaseBuilder(getContext(), TodoDatabase.class, "todo-db").allowMainThreadQueries().build();

        head_array = db.todoDao().getAllHead();
        desc_array = db.todoDao().getAllDesc();

        myAdapter = new MyAdapter(getChildFragmentManager());

        mPager = (ViewPager) view.findViewById(R.id.pager);
        mPager.setAdapter(myAdapter);
    }

    private class MyAdapter extends FragmentStatePagerAdapter {

        public MyAdapter(FragmentManager fm) {
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            return ArrayListFragment.newInstance(position, head_array, desc_array);
        }

        @Override
        public int getCount() {
            return head_array.size();
        }

        @Override
        public int getItemPosition(@NonNull Object object) {
            return POSITION_NONE;
        }
    }

    public static class ArrayListFragment extends ListFragment {
        int mNum;
        ArrayList<String> head_array, desc_array;
        Button btn_save;

        public int return_mNum(){
            return mNum;
        }

        static ArrayListFragment newInstance(int num, List<String> head_array, List<String> desc_array) {
            ArrayListFragment arrayListFragment = new ArrayListFragment();
            Bundle bundle = new Bundle();
            bundle.putInt("num", num);
            bundle.putStringArrayList("head_array", (ArrayList<String>) head_array);
            bundle.putStringArrayList("desc_array", (ArrayList<String>) desc_array);
            arrayListFragment.setArguments(bundle);
            return arrayListFragment;
        }

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mNum = getArguments() != null ? getArguments().getInt("num") : 1;
            head_array = getArguments().getStringArrayList("head_array");
            desc_array = getArguments().getStringArrayList("desc_array");
        }

        @Nullable
        @Override
        public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_pager_list, container, false);
            btn_save = v.findViewById(R.id.btn_save);

            final View head_tv = v.findViewById(R.id.head_tv);
            final View desc_tv = v.findViewById(R.id.desc_tv);

            if (head_array.size() == 0) {
                ((TextView) head_tv).setText(R.string.when_no_data_in_DB);
                ((TextView) desc_tv ).setText("");

                btn_save.setVisibility(View.INVISIBLE);
            } else {
                ((TextView) head_tv).setText(head_array.get(mNum));
                ((TextView) desc_tv ).setText(getString(Integer.parseInt(desc_array.get(mNum))));
            }
            return v;
        }
    }
}
英文翻译

I'm sorry a question that has already been answered in this web, but I can't find same case with mine.

I call lists of multiple columns from RoomDatabase for SetText in a ViewPager, and my question is how to dynamically update ViewPager when I delete record. In other questions I've checked, there was a single TextView in a ViewPager. But in my case, I assign arrays, that I received through bundle, into each TextView in ArrayListFragment class.

It's so frustrating after searching for what to do after 'myAdapter.notifyDataSetChanged()' in delete button.

I will really appreciate your help.

public class FragmentStateLibraryPagerSupport extends Fragment {

    MyAdapter myAdapter;
    ViewPager mPager;
    public List&lt;String&gt; head_array;
    public List&lt;String&gt; desc_array;
    TodoDatabase db;

    @Nullable
    @Override
    public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        final View root = inflater.inflate( R.layout.fragment_pager, null );
        Button btn_delete = root.findViewById( R.id.btn_delete );
        btn_delete.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayListFragment arrayListFragment = new ArrayListFragment();
                String head_array_text = head_array.get( arrayListFragment.return_mNum() );
                Log.e( &quot;head_array_text ::&quot; ,  head_array.get( arrayListFragment.return_mNum() ));

                TodoDatabase db = Room.databaseBuilder( getContext(), TodoDatabase.class, &quot;todo-db&quot; ).allowMainThreadQueries().build();
                db.todoDao().deleteRecord( head_array_text );
                myAdapter.notifyDataSetChanged();
            }
        } );
        return root;
    }
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated( view, savedInstanceState );
        db = Room.databaseBuilder( getContext(), TodoDatabase.class, &quot;todo-db&quot; ).allowMainThreadQueries().build();

        head_array = db.todoDao().getAllHead();
        desc_array = db.todoDao().getAllDesc();

        myAdapter = new MyAdapter( getChildFragmentManager() );

        mPager = (ViewPager) view.findViewById( R.id.pager );
        mPager.setAdapter( myAdapter );
    }
    private class MyAdapter extends FragmentStatePagerAdapter {

        public MyAdapter(FragmentManager fm) {
            super( fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT );
        }

        @NonNull
        @Override
        public Fragment getItem(int position) {
            return ArrayListFragment.newInstance( position, head_array, desc_array );
        }

        @Override
        public int getCount() {
                return head_array.size();
        }

        @Override
        public int getItemPosition(@NonNull Object object) {
            return POSITION_NONE;
        }
    }

    public static class ArrayListFragment extends ListFragment {
        int mNum;
        ArrayList&lt;String&gt; head_array, desc_array;
        Button btn_save;

        public int return_mNum(){
            return mNum;
        }

        static ArrayListFragment newInstance(int num, List&lt;String&gt; head_array, List&lt;String&gt; desc_array) {
            ArrayListFragment arrayListFragment = new ArrayListFragment();
            Bundle bundle = new Bundle();
            bundle.putInt( &quot;num&quot;, num );
            bundle.putStringArrayList( &quot;head_array&quot;, (ArrayList&lt;String&gt;) head_array );
            bundle.putStringArrayList( &quot;desc_array&quot;, (ArrayList&lt;String&gt;) desc_array );
            arrayListFragment.setArguments( bundle );
            return arrayListFragment;
        }

        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate( savedInstanceState );
            mNum = getArguments() != null ? getArguments().getInt( &quot;num&quot; ) : 1;
            head_array = getArguments().getStringArrayList( &quot;head_array&quot; );
            desc_array = getArguments().getStringArrayList( &quot;desc_array&quot; );
        }

        @Nullable
        @Override
        public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable Bundle savedInstanceState) {
            View v = inflater.inflate( R.layout.fragment_pager_list, container, false );
            btn_save = v.findViewById( R.id.btn_save );

            final View head_tv = v.findViewById( R.id.head_tv );
            final View desc_tv = v.findViewById( R.id.desc_tv );

            if (head_array.size() == 0) {
                ((TextView) head_tv).setText( R.string.when_no_data_in_DB );
                ((TextView) desc_tv ).setText( &quot;&quot; );

                btn_save.setVisibility( View.INVISIBLE );
            } else {
                ((TextView) head_tv).setText( head_array.get( mNum ) );
                ((TextView) desc_tv ).setText( getString( Integer.parseInt( desc_array.get( mNum ) ) ) );
            }
            return v;
        }
    }
}

答案1

得分: 0

public class DynamicFragmentPagerAdapter extends PagerAdapter {
    private static final String TAG = "DynamicFragmentPagerAdapter";

    private final FragmentManager fragmentManager;

    public static abstract class FragmentIdentifier implements Parcelable {
        private final String fragmentTag;
        private final Bundle args;

        public FragmentIdentifier(@NonNull String fragmentTag, @Nullable Bundle args) {
            this.fragmentTag = fragmentTag;
            this.args = args;
        }

        protected FragmentIdentifier(Parcel in) {
            fragmentTag = in.readString();
            args = in.readBundle(getClass().getClassLoader());
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(fragmentTag);
            dest.writeBundle(args);
        }

        protected final Fragment newFragment() {
            Fragment fragment = createFragment();
            Bundle oldArgs = fragment.getArguments();
            Bundle newArgs = new Bundle();
            if (oldArgs != null) {
                newArgs.putAll(oldArgs);
            }
            if (args != null) {
                newArgs.putAll(args);
            }
            fragment.setArguments(newArgs);
            return fragment;
        }

        protected abstract Fragment createFragment();
    }

    private ArrayList<FragmentIdentifier> fragmentIdentifiers = new ArrayList<>();

    private FragmentTransaction currentTransaction = null;

    private Fragment currentPrimaryItem = null;

    public DynamicFragmentPagerAdapter(FragmentManager fragmentManager) {
        this.fragmentManager = fragmentManager;
    }

    private int findIndexIfAdded(FragmentIdentifier fragmentIdentifier) {
        for (int i = 0, size = fragmentIdentifiers.size(); i < size; i++) {
            FragmentIdentifier identifier = fragmentIdentifiers.get(i);
            if (identifier.fragmentTag.equals(fragmentIdentifier.fragmentTag)) {
                return i;
            }
        }
        return -1;
    }

    public void addFragment(FragmentIdentifier fragmentIdentifier) {
        if (findIndexIfAdded(fragmentIdentifier) < 0) {
            fragmentIdentifiers.add(fragmentIdentifier);
            notifyDataSetChanged();
        }
    }

    public void removeFragment(FragmentIdentifier fragmentIdentifier) {
        int index = findIndexIfAdded(fragmentIdentifier);
        if (index >= 0) {
            fragmentIdentifiers.remove(index);
            notifyDataSetChanged();
        }
    }

    @Override
    public int getCount() {
        return fragmentIdentifiers.size();
    }

    @Override
    public void startUpdate(@NonNull ViewGroup container) {
        if (container.getId() == View.NO_ID) {
            throw new IllegalStateException("ViewPager with adapter " + this
                    + " requires a view id");
        }
    }

    @SuppressWarnings("ReferenceEquality")
    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (currentTransaction == null) {
            currentTransaction = fragmentManager.beginTransaction();
        }
        final FragmentIdentifier fragmentIdentifier = fragmentIdentifiers.get(position);
        // Do we already have this fragment?
        final String name = fragmentIdentifier.fragmentTag;
        Fragment fragment = fragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            currentTransaction.attach(fragment);
        } else {
            fragment = fragmentIdentifier.newFragment();
            currentTransaction.add(container.getId(), fragment, fragmentIdentifier.fragmentTag);
        }
        if (fragment != currentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }
        return fragment;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        if (currentTransaction == null) {
            currentTransaction = fragmentManager.beginTransaction();
        }
        currentTransaction.detach((Fragment) object);
    }

    @SuppressWarnings("ReferenceEquality")
    @Override
    public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        Fragment fragment = (Fragment) object;
        if (fragment != currentPrimaryItem) {
            if (currentPrimaryItem != null) {
                currentPrimaryItem.setMenuVisibility(false);
                currentPrimaryItem.setUserVisibleHint(false);
            }
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
            currentPrimaryItem = fragment;
        }
    }

    @Override
    public void finishUpdate(@NonNull ViewGroup container) {
        if (currentTransaction != null) {
            currentTransaction.commitNowAllowingStateLoss();
            currentTransaction = null;
        }
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return ((Fragment) object).getView() == view;
    }

    @Override
    public Parcelable saveState() {
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList("fragmentIdentifiers", fragmentIdentifiers);
        return bundle;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        Bundle bundle = ((Bundle) state);
        bundle.setClassLoader(loader);
        fragmentIdentifiers = bundle.getParcelableArrayList("fragmentIdentifiers");
    }
}
英文翻译

FragmentPagerAdapter is not really intended to support the ability of removing items (dynamic fragment item count).

For that you should use the following code, that tracks identifiers instead of Fragments by position.

public class DynamicFragmentPagerAdapter extends PagerAdapter {
private static final String TAG = &quot;DynamicFragmentPagerAdapter&quot;;

private final FragmentManager fragmentManager;

public static abstract class FragmentIdentifier implements Parcelable {
    private final String fragmentTag;
    private final Bundle args;
  
    public FragmentIdentifier(@NonNull String fragmentTag, @Nullable Bundle args) {
        this.fragmentTag = fragmentTag;
        this.args = args;
    }
  
    protected FragmentIdentifier(Parcel in) {
        fragmentTag = in.readString();
        args = in.readBundle(getClass().getClassLoader());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(fragmentTag);
        dest.writeBundle(args);
    }
  
    protected final Fragment newFragment() {
        Fragment fragment = createFragment();
        Bundle oldArgs = fragment.getArguments();
        Bundle newArgs = new Bundle();
        if(oldArgs != null) {
            newArgs.putAll(oldArgs);
        }
        if(args != null) {
            newArgs.putAll(args);
        }
        fragment.setArguments(newArgs);
        return fragment;
    }

    protected abstract Fragment createFragment();
}

private ArrayList&lt;FragmentIdentifier&gt; fragmentIdentifiers = new ArrayList&lt;&gt;();

private FragmentTransaction currentTransaction = null;

private Fragment currentPrimaryItem = null;

public DynamicFragmentPagerAdapter(FragmentManager fragmentManager) {
    this.fragmentManager = fragmentManager;
}

private int findIndexIfAdded(FragmentIdentifier fragmentIdentifier) {
    for (int i = 0, size = fragmentIdentifiers.size(); i &lt; size; i++) {
        FragmentIdentifier identifier = fragmentIdentifiers.get(i);
        if (identifier.fragmentTag.equals(fragmentIdentifier.fragmentTag)) {
            return i;
        }
    }
    return -1;
}

public void addFragment(FragmentIdentifier fragmentIdentifier) {
    if (findIndexIfAdded(fragmentIdentifier) &lt; 0) {
        fragmentIdentifiers.add(fragmentIdentifier);
        notifyDataSetChanged();
    }
}

public void removeFragment(FragmentIdentifier fragmentIdentifier) {
    int index = findIndexIfAdded(fragmentIdentifier);
    if (index &gt;= 0) {
        fragmentIdentifiers.remove(index);
        notifyDataSetChanged();
    }
}

@Override
public int getCount() {
    return fragmentIdentifiers.size();
}

@Override
public void startUpdate(@NonNull ViewGroup container) {
    if (container.getId() == View.NO_ID) {
        throw new IllegalStateException(&quot;ViewPager with adapter &quot; + this
                + &quot; requires a view id&quot;);
    }
}

@SuppressWarnings(&quot;ReferenceEquality&quot;)
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
    if (currentTransaction == null) {
        currentTransaction = fragmentManager.beginTransaction();
    }
    final FragmentIdentifier fragmentIdentifier = fragmentIdentifiers.get(position);
    // Do we already have this fragment?
    final String name = fragmentIdentifier.fragmentTag;
    Fragment fragment = fragmentManager.findFragmentByTag(name);
    if (fragment != null) {
        currentTransaction.attach(fragment);
    } else {
        fragment = fragmentIdentifier.newFragment();
        currentTransaction.add(container.getId(), fragment, fragmentIdentifier.fragmentTag);
    }
    if (fragment != currentPrimaryItem) {
        fragment.setMenuVisibility(false);
        fragment.setUserVisibleHint(false);
    }
    return fragment;
}

@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
    if (currentTransaction == null) {
        currentTransaction = fragmentManager.beginTransaction();
    }
    currentTransaction.detach((Fragment) object);
}

@SuppressWarnings(&quot;ReferenceEquality&quot;)
@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
    Fragment fragment = (Fragment) object;
    if (fragment != currentPrimaryItem) {
        if (currentPrimaryItem != null) {
            currentPrimaryItem.setMenuVisibility(false);
            currentPrimaryItem.setUserVisibleHint(false);
        }
        fragment.setMenuVisibility(true);
        fragment.setUserVisibleHint(true);
        currentPrimaryItem = fragment;
    }
}

@Override
public void finishUpdate(@NonNull ViewGroup container) {
    if (currentTransaction != null) {
        currentTransaction.commitNowAllowingStateLoss();
        currentTransaction = null;
    }
}

@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
    return ((Fragment) object).getView() == view;
}

@Override
public Parcelable saveState() {
    Bundle bundle = new Bundle();
    bundle.putParcelableArrayList(&quot;fragmentIdentifiers&quot;, fragmentIdentifiers);
    return bundle;
}

@Override
public void restoreState(Parcelable state, ClassLoader loader) {
    Bundle bundle = ((Bundle)state);
    bundle.setClassLoader(loader);
    fragmentIdentifiers = bundle.getParcelableArrayList(&quot;fragmentIdentifiers&quot;);
}
}

huangapple
  • 本文由 发表于 2020年3月16日 23:40:27
  • 转载请务必保留本文链接:https://java.coder-hub.com/60708953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定