Ниже приведен мой код, который имеет 3 Fragment classes
каждую из трех вкладок ViewPager
. У меня есть пункт меню. Как показано в onOptionsItemSelected()
, выбрав опцию, мне нужно обновить фрагмент, который в настоящее время виден. Чтобы обновить это, я должен вызвать метод, который находится в классе фрагмента. Может кто-нибудь подсказать, пожалуйста, как вызвать этот метод?
public class MainActivity extends ActionBarActivity {
ViewPager ViewPager;
TabsAdapter TabsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager = new ViewPager(this);
ViewPager.setId(R.id.pager);
setContentView(ViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Attaching the Tabs to the fragment classes and setting the tab title.
TabsAdapter = new TabsAdapter(this, ViewPager);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
FragmentClass1.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
FragmentClass2.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
FragmentClass3.class, null);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addText:
**// Here I need to call the method which exists in the currently visible Fragment class**
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
tabPosition = tab.getPosition();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getCount() {
return mTabs.size();
}
}
}
Предположим, что ниже приведен класс фрагмента с методом, который updateList()
я хочу вызвать:
public class FragmentClass1{
ArrayList<String> originalData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.frag1, container, false);
originalData = getOriginalDataFromDB();
return fragmentView;
}
public void updateList(String text)
{
originalData.add(text);
//Here I could do other UI part that need to added
}
}
Ответы:
Простой способ сделать это - использовать трюк, связанный с
FragmentPagerAdapter
реализацией:Пожалуйста, переосмыслите соглашение об именовании переменных, используя в качестве имени переменной имя класса, которое очень запутанно (поэтому нет
ViewPager ViewPager
, используйте,ViewPager mPager
например).источник
instantiateItem()
метода и получение ссылок на нужные фрагменты самостоятельно.mAdapter.getItem(position)
, офигенно ... По крайней мере, теперь я знаю, что другие 8512 испытаний не работали. Спасибоисточник
onPageSelected
/,onPageDeselected
и все мои фрагменты пейджера расширяют его. ЗатемsetPrimaryitem
можно вызывать эти методы соответствующим образом, когда пользователь перемещается на новую страницу. Это означает, что вы можете реализовать более ленивую стратегию загрузки данных на страницах, которые даже не отображаются. Однако вы должны иметь в виду, что во время перехода страницы выглядит лучше, если следующая страница уже заполнена данными, поэтому отложенная загрузка всех данныхonPageSelected
может быть не идеальной.if
заявление? Фрагмент просто вызываетequals
метод объекта, который является мелким сравнением. Так почему бы просто не всегда звонитьmCurrentFragment = ((Fragment) object);
?Прежде всего следите за всеми «активными» фрагментами страниц. В этом случае вы отслеживаете фрагменты страниц в FragmentStatePagerAdapter, который используется ViewPager.
Чтобы избежать ссылки на «неактивные» страницы фрагмента, вам необходимо реализовать метод destroyItem (...) FragmentStatePagerAdapter:
и когда вам нужно получить доступ к видимой в данный момент странице, вы затем звоните:
Где метод getFragment (int) в MyAdapter выглядит следующим образом:
Надеюсь, что это может помочь!
источник
Это единственный способ получить NullPointerException для переменных экземпляра определенных классов фрагментов. Это может быть полезно для тех, кто придерживается того же. В onOptionsItemSelected () я кодировал следующий способ:
источник
FragmentStatePagerAdapter
не переопределяя любой код. На самом деле, это должно быть так же просто, как функция просто вернутьviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
.FragmentStatePagerAdapter имеет открытый метод с именем instantiateItem, который возвращает ваш фрагмент на основе указанных значений параметров, этот метод имеет два параметра ViewGroup (ViewPager) и position.
Использовал этот метод для получения фрагмента указанной позиции,
источник
Я знаю, что слишком поздно, но у меня есть действительно простые способы сделать это,
// для фрагмента при 0 возможности
источник
Здесь есть много ответов, которые на самом деле не касаются основного факта, что на самом деле НЕТ СПОСОБА сделать это предсказуемо, и таким образом, что в какой-то момент в будущем вы не выстрелите себе в ногу.
FragmentStatePagerAdapter
это единственный класс, который знает, как надежно получить доступ к фрагментам, которые отслеживаются ...FragmentManager
любая попытка угадать идентификатор или тег фрагмента не является надежной, долгосрочной. И попытки отследить экземпляры вручную, вероятно, не будут работать хорошо, когда состояние будет сохранено / восстановлено, потому чтоFragmentStatePagerAdapter
вполне может не вызывать обратные вызовы, когда оно восстанавливает состояние.Единственное, что мне удалось сделать - это скопировать код
FragmentStatePagerAdapter
и добавить метод, который возвращает фрагмент с учетом позиции (mFragments.get(pos)
). Обратите внимание, что этот метод предполагает, что фрагмент действительно доступен (т.е. он был виден в какой-то момент).Если вы особенно любите приключения, вы можете использовать отражение, чтобы получить доступ к элементам частного
mFragments
списка, но тогда мы вернемся к исходной точке (название списка не обязательно останется прежним).источник
Приведите экземпляр полученной сверху строки к фрагменту, с которым вы хотите работать. Работает отлично.
это экземпляр пейджера, управляющий фрагментами.
источник
Чтобы получить ссылку на видимый в данный момент фрагмент, предположим, что у вас есть ссылка на
ViewPager
asmPager
. Затем следующие шаги получат ссылку наcurrentFragment
:PageAdapter adapter = mPager.getAdapter();
int fragmentIndex = mPager.getCurrentItem();
FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
Fragment currentFragment = fspa.getItem(fragmentIndex);
Единственная используемая линия 3 броска действительна обычно.
FragmentStatePagerAdapter
полезный адаптер для ViewPagerисточник
Лучший способ сделать это, просто вызвать CallingFragmentName фрагмент = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Он будет повторно создавать экземпляр вызывающего фрагмента, чтобы не вызывать исключение нулевого указателя и вызывать любой метод этого фрагмента.
источник
Текущий фрагмент:
Это работает, если вы создали проект с шаблоном панели вкладок фрагментов.
Обратите внимание, что это работает с реализацией шаблона активности с вкладками по умолчанию.
источник
Я использовал следующее:
источник
FragmentStatePagerAdapter
имеет частную переменную экземпляра с именемmCurrentPrimaryItem
типаFragment
. Можно только удивляться, почему разработчики Android не снабжали его геттером. Эта переменная создается вsetPrimaryItem()
методе. Итак, переопределите этот метод таким образом, чтобы получить ссылку на эту переменную. Я просто закончил тем, что объявил свое собственноеmCurrentPrimaryItem
и скопировал содержимоеsetPrimaryItem()
моего переопределения.В вашей реализации
FragmentStatePagerAdapter
:источник
Вы можете определить
PagerAdapter
как это, тогда вы сможете получить любойFragment
вViewPager
.Чтобы получить текущий
Fragment
источник
Когда мы используем viewPager, хорошим способом доступа к экземпляру фрагмента в деятельности является instantiateItem (viewpager, index). // index - индекс фрагмента, экземпляр которого вы хотите.
например, я обращаюсь к экземпляру фрагмента 1 index-
источник
В моей предыдущей реализации я хранил список дочерних фрагментов, чтобы иметь к ним доступ позже, но это оказалось неправильной реализацией, вызвавшей большие утечки памяти.
Я в конечном итоге с помощью
instantiateItem(...)
метода, чтобы получить текущий фрагмент:Или получить любой другой фрагмент на позиции:
Из документации :
источник
У меня была та же проблема, и я решил ее с помощью этого кода.
Просто замените имя MyFragment именем вашего фрагмента и добавьте id вашего контейнера фрагментов.
источник
Это более перспективно, чем принятый ответ:
источник
Рассматриваемый сценарий лучше обслуживается каждым фрагментом, добавляющим свои собственные пункты меню и непосредственно обрабатывающим onOptionsItemSelected (), как описано в официальной документации . Лучше избегать недокументированных уловок.
источник
ViewPager
проблему?После прочтения всех комментариев и ответов я собираюсь объяснить оптимальное решение этой проблемы. Лучший вариант - решение @ rik, поэтому мое улучшение основано на его.
Вместо того, чтобы спрашивать каждый FragmentClass как
Создайте свой собственный интерфейс и сделайте так, чтобы ваши дочерние фрагменты реализовали его, что-то вроде
Затем вы можете сделать что-то подобное, чтобы инициировать и обновить свои внутренние фрагменты.
PS Будьте осторожны с тем, куда вы помещаете этот код, если вы вызываете insatiateItem до того, как система фактически его создаст,
savedInstanceState
ваш дочерний фрагмент для этого будет нулевымВылетит ваше приложение.
Удачи
источник
На основании того, что он ответил @chahat jain:
«Когда мы используем viewPager, хорошим способом доступа к экземпляру фрагмента в действии является instantiateItem (viewpager, index). // index - индекс фрагмента, экземпляр которого вы хотите.»
Если вы хотите сделать это в kotlin
0 к экземпляру фрагмента 0
// ================================================ ========================= // // ##################### ######## Пример использования ################################# // // == ================================================== ===================== //
Вот полный пример, чтобы получить потерянное представление о
вот мой veiewPager в .xml файле
И домашняя активность, где я вставляю вкладку
источник
В моей деятельности я имею:
источник
Иногда фрагмент может отправить пустой объект, поэтому вы можете запустить новый Runnable, чтобы решить проблему при первой загрузке.
Спасибо, Рик
источник
Переопределите setPrimaryItem из вашего FragmentPagerAdapter: объект является видимым фрагментом:
источник
Просто возьмите текущий элемент из пейджера, а затем попросите у вашего адаптера фрагмент этой позиции.
источник
getItem
создать новый экземплярЧтобы получить текущий фрагмент - получите позицию в ViewPager в публичном void onPageSelected (final int position) , а затем
SECTNUM - аргумент позиции, назначенный в публичном статическом PlaceholderFragment newInstance (int sectionNumber);фрагмента
getChildFragmentManager () или getFragmentManager () - зависит от того, как создан SectionsPagerAdapter
источник
Вы можете реализовать BroadcastReceiver во Фрагменте и отправить Намерение из любого места. Получатель фрагмента может прослушивать конкретное действие и вызывать метод экземпляра.
Одно предостережение заключается в том, что компонент View уже создан и (и для некоторых операций, таких как прокрутка списка, ListView уже должен отображаться).
источник
Это самый простой взлом:
(код Котлина)
Просто позвони
instantiateItem(viewPager, viewPager.getCurrentItem()
и бросьFragment
. Ваш предмет уже будет создан. Чтобы быть уверенным, вы можете добавить чек дляgetCount
.Работает с обоими
FragmentPagerAdapter
иFragmentStatePagerAdapter
!источник
Если ваш пейджер находится внутри фрагмента, используйте это:
Где
R.id.myViewPagerId
находится идентификатор вашего ViewPager внутри XML-макета.источник
Вы можете объявить массив фрагментов как фрагменты регистра
Тогда вы можете использовать его как
источник