Crash on Rotation with this error: Fragment has not been attached yet
Crash on Rotation with this error: Fragment has not been attached yet
我有一个 Activity
和 02 tabLayout
我在我的第一个选项卡中添加了 First Fragment
,自从我在第二个选项卡中添加了我的 Second Fragment
之后,一切都很好
我的 Second Fragment
工作但是当我旋转设备时它会崩溃,这是我的代码和 logCat..
我试图以不同的方式附加我的FragmentTwo
到我的MainActivity
..谁能告诉我哪里出了问题&&我怎样才能正确地做到这一点?
提前致谢。
主要Activity:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.ic_tab_note,
R.drawable.ic_tab_calendar
};
private static final int TIME_DELAY = 2000;
private static long back_pressed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//////// TOOLBAR
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
actionBar.setDisplayHomeAsUpEnabled(true);
///////// DRAWER
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigationView =
(NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener
(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
mDrawerLayout.closeDrawers();
Toast.makeText(MainActivity.this,
menuItem.getTitle(),
Toast.LENGTH_LONG).show();
return true;
}
});
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentOne(), "ONE");
adapter.addFragment(new FragmentTwo(), "TWO");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
// return mFragmentTitleList.get(position);
return null;
}
}
}
片段二:
import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.interfaces.OnDayClickedListener;
import ir.mirrajabi.persiancalendar.core.interfaces.OnMonthChangedListener;
import ir.mirrajabi.persiancalendar.core.models.CalendarEvent;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;
public class FragmentTwo extends Fragment {
private View view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_two_layout,
container, false);
final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
final PersianDate today = calendar.getToday();
calendar.addLocalEvent(new CalendarEvent(
today, "Custom event", false
));
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, true), "Custom event 2", true
));
calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
@Override
public void onChanged(PersianDate date) {
Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
}
});
persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
@Override
public void onClick(PersianDate date) {
for (CalendarEvent e : calendar.getAllEventsForDay(date))
Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, false), "Some event that will be added in runtime", false
));
persianCalendarView.update();
}
});
calendar.setHighlightOfficialEvents(false);
TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
TextView txtYear = (TextView) view.findViewById(R.id.txt_year);
String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
+ calendar.getMonthName(today);
txtDayMonth.setText(dayAndMonth);
txtYear.setText(calendar.formatNumber(today.getYear()));
calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
persianCalendarView.update();
return view;
}
}
这是我的 activity_main.xml
:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout
android:id="@+id/base2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:tabGravity="fill"
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
<RelativeLayout
android:id="@+id/relativee"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout_weight="1"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>
这里是 fragment_two_layout.xml
:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp">
<ir.mirrajabi.persiancalendar.PersianCalendarView
android:id="@+id/persian_calendar"
android:layout_width="match_parent"
android:layout_height="290sp"
app:pcv_colorBackground="#292929"
app:pcv_colorDayName="#bab6b6"
app:pcv_colorHoliday="#ffd506"
app:pcv_colorHolidaySelected="#f1f2f3"
app:pcv_colorNormalDaySelected="#d9d9d9"
app:pcv_colorNormalDay="#f3f4f5"
app:pcv_eventUnderlineColor="#02f0f0"
app:pcv_fontSize="20sp"
app:pcv_headersFontSize="14sp"/>
</android.support.v7.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="8dp">
<TextView
android:id="@+id/txt_day_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:layout_gravity="center_horizontal"
android:textSize="30sp"/>
<TextView
android:id="@+id/txt_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="@color/colorAccent"
android:textSize="20sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<Button
android:id="@+id/change_to_ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change to Gregorian Calendar"
android:textSize="14dp"/>
</LinearLayout>
</LinearLayout>
logCat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.drgnme.listhamrah/com.drgnme.listhamrah.MainActivity}: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095)
at android.app.ActivityThread.access00(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.support.v4.app.Fragment.instantiateChildFragmentManager(Fragment.java:2195)
at android.support.v4.app.Fragment.getChildFragmentManager(Fragment.java:745)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.createViewPagers(CalendarFragment.java:55)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.access[=14=]0(CalendarFragment.java:27)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.update(CalendarFragment.java:46)
at ir.mirrajabi.persiancalendar.PersianCalendarView.update(PersianCalendarView.java:116)
at com.drgnme.listhamrah.FragmentTwo.onCreateView(FragmentTwo.java:87)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2239)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1332)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1574)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1641)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2959)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:550)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1238)
at android.app.Activity.performStart(Activity.java:6340)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095)
at android.app.ActivityThread.access00(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
将以下所有代码移至onActivityCreated()
:
final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
final PersianDate today = calendar.getToday();
calendar.addLocalEvent(new CalendarEvent(
today, "Custom event", false
));
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, true), "Custom event 2", true
));
calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
@Override
public void onChanged(PersianDate date) {
Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
}
});
persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
@Override
public void onClick(PersianDate date) {
for (CalendarEvent e : calendar.getAllEventsForDay(date))
Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, false), "Some event that will be added in runtime", false
));
persianCalendarView.update();
}
});
calendar.setHighlightOfficialEvents(false);
TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
TextView txtYear = (TextView) view.findViewById(R.id.txt_year);
String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
+ calendar.getMonthName(today);
txtDayMonth.setText(dayAndMonth);
txtYear.setText(calendar.formatNumber(today.getYear()));
calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
persianCalendarView.update();
最佳做法是除了膨胀内部布局外不做任何工作 onCreateView()
问题不在你的应用程序中,问题在 PersianCalendar Lib 中,
如果您在 PersianCalendarView.java 中检查它们的实现,则您正在 Fragment class 的布局中膨胀 PersianCalendarView,1. 他们正在膨胀一种布局,并且他们正试图在该布局中添加一个 Fragment在那个 FragmentManager 中,它工作正常。 2. 但不仅如此,在该片段中,他们还试图使用 getChildFragmentManager()
添加 ViewPager 问题只出现在她身上。
你可以问为什么?已经有一个 FragmentManager 添加了这个 Fragment,当时它工作正常但现在它崩溃了,为此,您可以检查 this S0 Answer
中那两个 FragmnetManger 之间的区别
对于这个问题,你可以做3件事,
1. 你可以给他们建票,等结果
2. 你可以解决这个问题
3. 不用在布局中添加,只需在片段中创建一个 ViewGroup,当调用 onActivtyCreated 时,您可以添加该布局运行时。
已编辑
我尝试了那个示例,并尝试将它添加到 Fragment 中,我遇到的问题是,实际上 CalendarView 片段没有附加,即使我们的 Fragment 附加到 Activity,正如我在解决方案中提到的3 说我们可以把它加在onActivtyCreated
里面是错误的。
那我们暂时怎么解决呢?
我通过在 onStart
中添加视图来解决(我知道这是错误的地方,这将在 Fragment 的生命周期中调用多次),但是我们可以添加一些逻辑,我们可以添加这个日历只查看一次以使其现在工作,直到他们的库中的开发修复。
我的样本:
我的片段布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ir.mirrajabi.pc.sample.BlankFragment">
<LinearLayout
android:id="@+id/calendar_container"
android:layout_width="match_parent"
android:layout_height="290dp"
android:orientation="vertical"/>
<TextView
android:id="@+id/txt_day_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#f0f2f3"
android:textSize="30sp"/>
<TextView
android:id="@+id/txt_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#c6d9e2"
android:textSize="20sp"/>
</FrameLayout>
片段代码
public class BlankFragment extends Fragment {
private LinearLayout mLinearLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank, container, false);
mLinearLayout= (LinearLayout) view.findViewById(R.id.calendar_container);
return view;
}
@Override
public void onStart() {
super.onStart();
final PersianCalendarView persianCalendarView = new PersianCalendarView(getContext());
// All your remaining PersianCalendarView implementation code here
mLinearLayout.addView(persianCalendarView);
}
}
注:
If you take above approach, Please add some logic and make sure it's
not adding multiple time when onStart calls in the Fragment.
只需将 persianCalendarView.update()
行移动到 FragmentTwo
的 onAttach
中并将其从 onCreate()
中删除:
@Override
public void onAttachFragment(Fragment childFragment) {
super.onAttachFragment(childFragment);
persianCalendarView.update();
}
同时从 persianCalendarView
的 OnDayClickedListener
中删除 update()
。我在测试时添加了该行,但忘记将其从示例应用程序中删除。 您不必更新persianCalendarView
除非您需要更改主题或在运行时添加事件 .
我有一个 Activity
和 02 tabLayout
我在我的第一个选项卡中添加了 First Fragment
,自从我在第二个选项卡中添加了我的 Second Fragment
之后,一切都很好
我的 Second Fragment
工作但是当我旋转设备时它会崩溃,这是我的代码和 logCat..
我试图以不同的方式附加我的FragmentTwo
到我的MainActivity
..谁能告诉我哪里出了问题&&我怎样才能正确地做到这一点?
提前致谢。
主要Activity:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.ic_tab_note,
R.drawable.ic_tab_calendar
};
private static final int TIME_DELAY = 2000;
private static long back_pressed;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//////// TOOLBAR
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
actionBar.setDisplayHomeAsUpEnabled(true);
///////// DRAWER
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigationView =
(NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener
(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
mDrawerLayout.closeDrawers();
Toast.makeText(MainActivity.this,
menuItem.getTitle(),
Toast.LENGTH_LONG).show();
return true;
}
});
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FragmentOne(), "ONE");
adapter.addFragment(new FragmentTwo(), "TWO");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
// return mFragmentTitleList.get(position);
return null;
}
}
}
片段二:
import ir.mirrajabi.persiancalendar.PersianCalendarView;
import ir.mirrajabi.persiancalendar.core.PersianCalendarHandler;
import ir.mirrajabi.persiancalendar.core.interfaces.OnDayClickedListener;
import ir.mirrajabi.persiancalendar.core.interfaces.OnMonthChangedListener;
import ir.mirrajabi.persiancalendar.core.models.CalendarEvent;
import ir.mirrajabi.persiancalendar.core.models.PersianDate;
public class FragmentTwo extends Fragment {
private View view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_two_layout,
container, false);
final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
final PersianDate today = calendar.getToday();
calendar.addLocalEvent(new CalendarEvent(
today, "Custom event", false
));
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, true), "Custom event 2", true
));
calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
@Override
public void onChanged(PersianDate date) {
Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
}
});
persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
@Override
public void onClick(PersianDate date) {
for (CalendarEvent e : calendar.getAllEventsForDay(date))
Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, false), "Some event that will be added in runtime", false
));
persianCalendarView.update();
}
});
calendar.setHighlightOfficialEvents(false);
TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
TextView txtYear = (TextView) view.findViewById(R.id.txt_year);
String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
+ calendar.getMonthName(today);
txtDayMonth.setText(dayAndMonth);
txtYear.setText(calendar.formatNumber(today.getYear()));
calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
persianCalendarView.update();
return view;
}
}
这是我的 activity_main.xml
:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<RelativeLayout
android:id="@+id/base2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:tabGravity="fill"
android:theme="@style/ThemeOverlay.AppCompat.Dark"/>
<RelativeLayout
android:id="@+id/relativee"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout_weight="1"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer"/>
</android.support.v4.widget.DrawerLayout>
这里是 fragment_two_layout.xml
:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp">
<ir.mirrajabi.persiancalendar.PersianCalendarView
android:id="@+id/persian_calendar"
android:layout_width="match_parent"
android:layout_height="290sp"
app:pcv_colorBackground="#292929"
app:pcv_colorDayName="#bab6b6"
app:pcv_colorHoliday="#ffd506"
app:pcv_colorHolidaySelected="#f1f2f3"
app:pcv_colorNormalDaySelected="#d9d9d9"
app:pcv_colorNormalDay="#f3f4f5"
app:pcv_eventUnderlineColor="#02f0f0"
app:pcv_fontSize="20sp"
app:pcv_headersFontSize="14sp"/>
</android.support.v7.widget.CardView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="8dp">
<TextView
android:id="@+id/txt_day_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:layout_gravity="center_horizontal"
android:textSize="30sp"/>
<TextView
android:id="@+id/txt_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="@color/colorAccent"
android:textSize="20sp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<Button
android:id="@+id/change_to_ad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change to Gregorian Calendar"
android:textSize="14dp"/>
</LinearLayout>
</LinearLayout>
logCat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.drgnme.listhamrah/com.drgnme.listhamrah.MainActivity}: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095)
at android.app.ActivityThread.access00(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Fragment has not been attached yet.
at android.support.v4.app.Fragment.instantiateChildFragmentManager(Fragment.java:2195)
at android.support.v4.app.Fragment.getChildFragmentManager(Fragment.java:745)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.createViewPagers(CalendarFragment.java:55)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.access[=14=]0(CalendarFragment.java:27)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment.update(CalendarFragment.java:46)
at ir.mirrajabi.persiancalendar.PersianCalendarView.update(PersianCalendarView.java:116)
at com.drgnme.listhamrah.FragmentTwo.onCreateView(FragmentTwo.java:87)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2239)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1332)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1574)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1641)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2959)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:550)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1238)
at android.app.Activity.performStart(Activity.java:6340)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2397)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4095)
at android.app.ActivityThread.access00(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5451)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
将以下所有代码移至onActivityCreated()
:
final PersianCalendarView persianCalendarView = (PersianCalendarView) view.findViewById(R.id.persian_calendar);
final PersianCalendarHandler calendar = persianCalendarView.getCalendar();
final PersianDate today = calendar.getToday();
calendar.addLocalEvent(new CalendarEvent(
today, "Custom event", false
));
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, true), "Custom event 2", true
));
calendar.setOnMonthChangedListener(new OnMonthChangedListener() {
@Override
public void onChanged(PersianDate date) {
Toast.makeText(getActivity(), calendar.getMonthName(date), Toast.LENGTH_SHORT).show();
}
});
persianCalendarView.setOnDayClickedListener(new OnDayClickedListener() {
@Override
public void onClick(PersianDate date) {
for (CalendarEvent e : calendar.getAllEventsForDay(date))
Toast.makeText(getActivity(), e.getTitle(), Toast.LENGTH_LONG).show();
calendar.addLocalEvent(new CalendarEvent(
today.clone().rollDay(2, false), "Some event that will be added in runtime", false
));
persianCalendarView.update();
}
});
calendar.setHighlightOfficialEvents(false);
TextView txtDayMonth = (TextView) view.findViewById(R.id.txt_day_month);
TextView txtYear = (TextView) view.findViewById(R.id.txt_year);
String dayAndMonth = calendar.getWeekDayName(today) + calendar.formatNumber(today.getDayOfMonth())
+ calendar.getMonthName(today);
txtDayMonth.setText(dayAndMonth);
txtYear.setText(calendar.formatNumber(today.getYear()));
calendar.setColorBackground(getResources().getColor(android.R.color.holo_blue_dark));
persianCalendarView.update();
最佳做法是除了膨胀内部布局外不做任何工作 onCreateView()
问题不在你的应用程序中,问题在 PersianCalendar Lib 中,
如果您在 PersianCalendarView.java 中检查它们的实现,则您正在 Fragment class 的布局中膨胀 PersianCalendarView,1. 他们正在膨胀一种布局,并且他们正试图在该布局中添加一个 Fragment在那个 FragmentManager 中,它工作正常。 2. 但不仅如此,在该片段中,他们还试图使用 getChildFragmentManager()
添加 ViewPager 问题只出现在她身上。
你可以问为什么?已经有一个 FragmentManager 添加了这个 Fragment,当时它工作正常但现在它崩溃了,为此,您可以检查 this S0 Answer
中那两个 FragmnetManger 之间的区别对于这个问题,你可以做3件事, 1. 你可以给他们建票,等结果 2. 你可以解决这个问题 3. 不用在布局中添加,只需在片段中创建一个 ViewGroup,当调用 onActivtyCreated 时,您可以添加该布局运行时。
已编辑
我尝试了那个示例,并尝试将它添加到 Fragment 中,我遇到的问题是,实际上 CalendarView 片段没有附加,即使我们的 Fragment 附加到 Activity,正如我在解决方案中提到的3 说我们可以把它加在onActivtyCreated
里面是错误的。
那我们暂时怎么解决呢?
我通过在 onStart
中添加视图来解决(我知道这是错误的地方,这将在 Fragment 的生命周期中调用多次),但是我们可以添加一些逻辑,我们可以添加这个日历只查看一次以使其现在工作,直到他们的库中的开发修复。
我的样本:
我的片段布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="ir.mirrajabi.pc.sample.BlankFragment">
<LinearLayout
android:id="@+id/calendar_container"
android:layout_width="match_parent"
android:layout_height="290dp"
android:orientation="vertical"/>
<TextView
android:id="@+id/txt_day_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#f0f2f3"
android:textSize="30sp"/>
<TextView
android:id="@+id/txt_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="#c6d9e2"
android:textSize="20sp"/>
</FrameLayout>
片段代码
public class BlankFragment extends Fragment {
private LinearLayout mLinearLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_blank, container, false);
mLinearLayout= (LinearLayout) view.findViewById(R.id.calendar_container);
return view;
}
@Override
public void onStart() {
super.onStart();
final PersianCalendarView persianCalendarView = new PersianCalendarView(getContext());
// All your remaining PersianCalendarView implementation code here
mLinearLayout.addView(persianCalendarView);
}
}
注:
If you take above approach, Please add some logic and make sure it's not adding multiple time when onStart calls in the Fragment.
只需将 persianCalendarView.update()
行移动到 FragmentTwo
的 onAttach
中并将其从 onCreate()
中删除:
@Override
public void onAttachFragment(Fragment childFragment) {
super.onAttachFragment(childFragment);
persianCalendarView.update();
}
同时从 persianCalendarView
的 OnDayClickedListener
中删除 update()
。我在测试时添加了该行,但忘记将其从示例应用程序中删除。 您不必更新persianCalendarView
除非您需要更改主题或在运行时添加事件 .