Подтвердить что ты не робот

Обновить фрагмент из ViewPager

У меня есть Activity с ViewPager. У меня также есть Dialog, который будет извлекать список с некоторыми элементами, которые пользователь выберет. Теперь, как я могу обновить Fragment, где Элементы должны отображаться как новые представления, прикрепленные к этому фрагменту?

Вот мой адаптер ViewPager:

public static class MyAdapter extends FragmentPagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return 1;
    }

    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
        case 0:
            return new Fragment1();

        default:
            return null;
        }
    }
}

Теперь, вот Fragment:

public class Fragment1 extends Fragment{

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
}

@Override
public ViewGroup onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    ViewGroup view = (ViewGroup)inflater.inflate(R.layout.screen1, container, false);
    }
    return view;
}

}

Это метод, который я хочу использовать для добавления элементов в мой Fragment

private void addItem() {

    // Instantiate a new "row" view.

    final ViewGroup[] newViews = new ViewGroup[selectedItems.length];


    for(int i = 0; i < selectedItems.length; i++){
        newViews[i] = (ViewGroup) LayoutInflater.from(this).inflate(
                    R.layout.animated_layout_item, mContainerView, false);

        // Set the text in each new row.
        ((TextView) newViews[i].findViewById(android.R.id.text1)).setText(selectedItems[i]);

        // Because mContainerView has android:animateLayoutChanges set to true,
        // adding this view is automatically animated.

            mContainerView.addView(newViews[i], 0);


        // Set a click listener for the "X" button in the row that will remove the row.
        OnClickListener listener = new MyAddItemListener(newViews[i], mContainerView, this);
        newViews[i].findViewById(R.id.delete_button).setOnClickListener(listener);

    }


}
4b9b3361

Ответ 1

Обновить фрагмент из ViewPager

Вам нужно реализовать метод getItemPosition(Object obj).

Этот метод вызывается, когда вы вызываете

notifyDataSetChanged()

на ViewPagerAdaper. Неявно этот метод возвращает значение POSITION_UNCHANGED, что означает что-то вроде этого: "Фрагмент - это то, где он должен быть, поэтому ничего не меняйте".

Итак, если вам нужно обновить Фрагмент, вы можете сделать это с помощью

  • Всегда возвращайте метод POSITION_NONE из getItemPosition(). Это означает: "Фрагмент должен всегда воссоздаваться"
  • Вы можете создать некоторый метод update(), который будет обновлять ваши Фрагмент (фрагмент обрабатывает сами обновления)

Пример второго подхода:

public interface Updateable {
   public void update();
}


public class MyFragment extends Fragment implements Updateable {

   ...

   public void update() {
     // do your stuff
   }
}

И в FragmentPagerAdapter вы сделаете что-то вроде этого:

@Override
public int getItemPosition(Object object) {
   MyFragment f = (MyFragment ) object;
   if (f != null) {
      f.update();
   }
  return super.getItemPosition(object);
}

И если вы выберете первый подход, это может выглядеть так:

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

Примечание: Стоит подумать о том, какой подход вы подберете.

Ответ 2

Я столкнулся с проблемой несколько раз, чтобы в этом случае всегда избегать FragmentPagerAdapter и использовать FragmentStatePagerAdapter.

Это работает для меня. Я надеюсь, что это сработает и для вас.

Ответ 3

Я реализую демонстрацию приложения после ответа Саймона. Только для тех, кто ищет этот вопрос.

Вы можете получить исходный код на GitHub

введите описание изображения здесь

Ответ 4

В вашем PagerAdapter переопределить getItemPosition

@Override
public int getItemPosition(Object object) {
// POSITION_NONE makes it possible to reload the PagerAdapter
return POSITION_NONE;
}

После этого добавьте viewPager.getAdapter(). notifyDataSetChanged(); этот код, как показано ниже

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            viewPager.getAdapter().notifyDataSetChanged();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

должен работать.

Ответ 5

Очень просто переопределить метод в фрагменте:

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if(isVisibleToUser){
        actionView();
    }
    else{
        //no
    }      
}

Ответ 6

Вы можете обновить фрагмент двумя способами,

Первый способ

как @Sajmon

Вам нужно реализовать метод getItemPosition(Object obj).

Этот метод вызывается, когда вы вызываете

notifyDataSetChanged()

Вы можете найти пример в Github и более подробную информацию в этом пост.

введите описание изображения здесь

Второй способ

Мой подход к обновлению фрагментов в viewpager заключается в использовании метода setTag() для любого инстанцированного представления в методе instantiateItem(). Поэтому, когда вы хотите изменить данные или сделать недействительным требуемое представление, вы можете вызвать метод findViewWithTag() на ViewPager, чтобы получить ранее созданное представление и изменить/использовать его, как вы хотите, без необходимости удаления/создания нового представления каждый раз, когда вы хотите обновить некоторое значение.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object object = super.instantiateItem(container, position);
    if (object instanceof Fragment) {
        Fragment fragment = (Fragment) object;
        String tag = fragment.getTag();
        mFragmentTags.put(position, tag);
    }
    return object;
}

public Fragment getFragment(int position) {
    Fragment fragment = null;
    String tag = mFragmentTags.get(position);
    if (tag != null) {
        fragment = mFragmentManager.findFragmentByTag(tag);
    }
    return fragment;
}

Вы можете найти пример в Github или более подробную информацию в этом сообщение:

введите описание изображения здесь

Ответ 7

Принятый ответ не понимает, поэтому добавлено простое решение. после длительной борьбы найти Рабочее решение.

Просто сообщите об этом адаптеру, он работает потрясающе,

Код ссылки

 void setAdapter(int position) {
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);
        // when notify then set manually current position.
        viewPager.setCurrentItem(position);
        pagerAdapter.notifyDataSetChanged();
    }

вызывают этот код при настройке адаптера и когда вы хотите обновить интерфейс.

В своем фрагменте добавьте этот код для обновления

((YourActivityName) getContext()).setAdapter(selectedTabPosition);

Используйте instanceof для контекста трансляции.

Этот общий код помогает только тем, кто находит решение.

Ответ 8

Очень простое, но эффективное решение обновить виды фрагментов. Используйте метод setUserVisibleHint(). Он будет вызван, когда фрагмент будет видимым для пользователя. Там вы можете обновить наш вид (setText() или setVisibility() и т.д.)

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if(isVisibleToUser){
       //Write your code to be executed when it is visible to user
    }
}

Это сработало в моем случае. Надеюсь, поможет!

Ответ 9

Если вы используете Kotlin, вы можете сделать следующее:

1. По первому, вам следует создать Interface и внедрить его в ваш Fragment

interface RefreshData {
    fun refresh()
}

class YourFragment : Fragment(), RefreshData {
    ...
    override fun refresh() {
        //do what you want
    }
}

2. Следующий шаг - добавление OnPageChangeListener в ваш ViewPager

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    override fun onPageScrollStateChanged(state: Int) { }

    override fun onPageSelected(position: Int) {
        viewPagerAdapter.notifyDataSetChanged()
        viewPager.currentItem = position
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { }
})

3. переопределить getItemPosition в вашем Adapter

override fun getItemPosition(obj: Any): Int {
    if (obj is RefreshData) {
        obj.refresh()
    }
    return super.getItemPosition(obj)
}

Ответ 10

Возможно, ваш метод добавления элементов в фрагмент должен быть общедоступным (помещен в желаемый фрагмент) и должен иметь параметр того же типа, что и selectedItems..

Это сделает его видимым из активности, в котором будет выбран массив элементов и voila.

p.s. лучше назовите его addItemsFromArray(typeOfSelectedItems[] pSelectedItems) причина name addItem() довольно непривычно

Изменить: stackoverflow просто предложил похожую тему:) Посмотрите здесь для детальной реализации идеи..:)

Ответ 11

1) Создайте обработчик в фрагменте, который вы хотите обновить.

public static Handler sUpdateHandler;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ...

        sUpdateHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // call you update method here.
            }
        };
    }

2) В Activity/Fragment/Dialog, где бы вы не вызвали вызов обновления, получите ссылку на этот обработчик и отправьте сообщение (сообщив об обновлении вашего фрагмента)

// Check if the fragment is visible by checking if the handler is null or not.
Handler handler = TaskTabCompletedFragment.sUpdateHandler;
if (handler != null) {
    handler.obtainMessage().sendToTarget();
}

Ответ 12

у меня было 4 фрагмента в ViewPager, но я хотел обновить только один фрагмент "FavoriteFragment" в позиции 0 viewPager, каждый раз, когда пользователь нажимает на этот фрагмент. но ни один из приведенных выше кодов не помог мне перезагрузить только тот фрагмент, который я хочу. так что я попробовал это, и это работает для меня:

в моем любимом фрагменте я переопределил onResume()

@Override
    public void onResume() {
        super.onResume();
        updateUI(); // code to update the UI in the fragment
    }

в Activity, где размещается viewPager, переопределите addOnPageChangeListener() и добавьте этот код

mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);

                if(position == 0) { // 0 = the first fragment in the ViewPager, in this case, the fragment i want to refresh its UI
                    FavoritesFragment fragment = (FavoritesFragment) mViewPager.getAdapter().instantiateItem(mViewPager, position); 
                    fragment.onResume(); // here i call the onResume of the fragment, where i have the method updateUI() to update its UI
                    mViewPager.getAdapter().notifyDataSetChanged();
                }
            }
        });

и это прекрасно работает для меня, чтобы обновить/перезагрузить только один фрагмент, который я хочу.

Ответ 13

Поскольку ни один из приведенных выше ответов не помог мне, вот мое решение:

Я объединил POSITION_NONE с загрузкой в setUserVisibleHint(boolean isVisibleToUser) вместо onStart()

Как видно здесь: fooobar.com/info/13824/...

Во Fragment:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}

и в FragmentStatePagerAdapter как видно из верхнего ответа от Саймона Дорокиака fooobar.com/info/133497/...:

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

Теперь фрагменты загружают данные в свои представления каждый раз, когда они показываются пользователю.