Как создать диалог Android с вкладками, содержащий фрагменты?
Может ли кто-нибудь указать мне на пример или показать мне, как создать простой Tabbed Dialog
в Android, где содержимое каждой вкладки Fragments
? Все примеры / учебники, которые я нашел, посвящены фрагментам и вкладкам, но ничего конкретного DialogFragments
,
Документация для FragmentTabHost
показывает, как создавать вкладки внутри обычных фрагментов, используя getChildFragmentManager()
, Я предполагаю, что это также должно работать, когда фрагмент DialogFragment
но когда я пытаюсь это сделать, я получаю:
java.lang.IllegalStateException: Fragment does not have a view at android.support.v4.app.Fragment$1.findViewById(Fragment.java:1425)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:901)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
...
Вот мой код для настройки представления (которое затем передается AlertDialog.setView()
):
private void setupView(View v) {
mTabHost = (FragmentTabHost) v.findViewById(android.R.id.tabhost);
mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
MyDialogFragment.class, null);
}
4 ответа
Потратил много времени, чтобы заставить его работать, но не повезло. Единственное решение, которое я нашел, - создать фиктивный фрагмент tabhost и использовать viewpager с фрагментами вместо фрагментов tabhost.
voters_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
>
<android.support.v4.app.FragmentTabHost
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tabs"
>
</android.support.v4.app.FragmentTabHost>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
</LinearLayout>
Класс диалога, хитрость заключается в использовании onCreateView, а не onCreateDialog
public class VotersDialog extends DialogFragment {
private FragmentTabHost mTabHost;
private ViewPager viewPager;
private VotersPagerAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.voters_dialog, container);
getDialog().setTitle(getArguments().getString("title"));
mTabHost = (FragmentTabHost) view.findViewById(R.id.tabs);
mTabHost.setup(getActivity(), getChildFragmentManager());
mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Плюсов"), Fragment.class, null);
mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Минусов"), Fragment.class, null);
adapter = new VotersPagerAdapter(getChildFragmentManager(), getArguments());
adapter.setTitles(new String[]{"Плюсов", "Минусов"});
viewPager = (ViewPager)view.findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int i, float v, int i2) {
}
@Override
public void onPageSelected(int i) {
mTabHost.setCurrentTab(i);
}
@Override
public void onPageScrollStateChanged(int i) {
}
});
mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
@Override
public void onTabChanged(String s) {
int i = mTabHost.getCurrentTab();
viewPager.setCurrentItem(i);
}
});
return view;
}
public class VotersPagerAdapter extends FragmentPagerAdapter {
Bundle bundle;
String [] titles;
public VotersPagerAdapter(FragmentManager fm) {
super(fm);
}
public VotersPagerAdapter(FragmentManager fm, Bundle bundle) {
super(fm);
this.bundle = bundle;
}
@Override
public Fragment getItem(int num) {
Fragment fragment = new VotersListFragment();
Bundle args = new Bundle();
args.putSerializable("voters",bundle.getSerializable( num == 0 ? "pros" : "cons"));
fragment.setArguments(args);
return fragment;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
public void setTitles(String[] titles) {
this.titles = titles;
}
}
public static class VotersListFragment extends ListFragment {
List<String> voters;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
voters = (ArrayList) getArguments().getSerializable("voters");
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, voters);
setListAdapter(adapter);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity(), ProfileActivity_.class);
String login = voters.get(i);
intent.putExtra("login", Utils.encodeString(login.substring(0, login.indexOf("(")).trim()));
startActivity(intent);
}
});
}
}
}
Вот результат, теперь вы можете нажать вкладки или пролистать фрагменты
Я искал то же решение, но у меня ничего не получилось, поэтому я создал свой собственный диалог с вкладками Android, содержащий фрагменты. может быть, это может помочь кому-то.
Вы можете оформить полный исходный код отсюда
Вы должны использовать DialogFragment
, TabLayout
а также ViewPager
, Например, вид вашего фрагмента диалога может выглядеть так:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.view.ViewPager
android:id="@+id/masterViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Создайте свой адаптер и убедитесь, что вы переопределяете getPageTitleMethod, например:
public class CustomAdapter extends FragmentPagerAdapter {
List<Fragment> mFragmentCollection = new ArrayList<>();
List<String> mTitleCollection = new ArrayList<>();
public CustomAdapter(FragmentManager fm) {
super(fm);
}
public void addFragment(String title, Fragment fragment)
{
mTitleCollection.add(title);
mFragmentCollection.add(fragment);
}
//Needed for
@Override
public CharSequence getPageTitle(int position) {
return mTitleCollection.get(position);
}
@Override
public Fragment getItem(int position) {
return mFragmentCollection.get(position);
}
@Override
public int getCount() {
return mFragmentCollection.size();
}
}
в OnCreateView
вашего диалога, вы должны настроить свой viewpager с помощью tabLayout:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.dialog_sample,container,false);
tabLayout = (TabLayout) rootview.findViewById(R.id.tabLayout);
viewPager = (ViewPager) rootview.findViewById(R.id.masterViewPager);
CustomAdapter adapter = new CustomAdapter(getChildFragmentManager());
adapter.addFragment("Boy",CustomFragment.createInstance("John"));
adapter.addFragment("Girl",CustomFragment.createInstance("Stacy"));
adapter.addFragment("Robot",CustomFragment.createInstance("Aeon"));
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
return rootview;
}
У меня есть сообщение в блоге, написанное здесь: здесь.
Попробуйте вместо этого использовать DialogFragment, и в макете своего диалогового фрагмента добавьте LinearLayout для fragTransaction.
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
String Tag = fragment.getClass().getSimpleName();
t.replace(R.id.llTabFragmentContainer, fragment, Tag);
t.commit();
фрагмент - это фрагмент вашей вкладки. cheeers