i have an Activity
with 02 tabLayout
i added First Fragment
in my first tab, every thing was just fine since i added my Second Fragment
in second tab
my Second Fragment
works but when i rotate the device it'll be crash, here is my codes and logCat..
i tried to attach my FragmentTwo
to my MainActivity
in different ways.. can anybody tell me what's wroNg && how can i do this correctly?
Thanks in advancE.
Main 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;
}
}
}
FragmentTwo:
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;
}
}
and here is my 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>
and here is 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.access$1000(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$000(CalendarFragment.java:27)
at ir.mirrajabi.persiancalendar.core.fragments.CalendarFragment$1.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.access$1000(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)
Problem is not in your app, Problem is in PersianCalendar Lib,
You are inflating PersianCalendarView in your layout in the Fragment class if you check their implementation in PersianCalendarView.java, 1. they are inflating one layout and they are trying to add one Fragment in that layout in that FragmentManager and its working fine. 2. but not only that in that Fragment they are trying to add ViewPager using getChildFragmentManager()
Problem comes her only.
You can ask why? In already one FragmentManager added this Fragment that time its working fine but now it's crashing, For that, you can check the difference between that 2 FragmnetManger in this S0 Answer
For this problem, you can do 3 things, 1. You can create ticket to them and wait for the result 2. You can fix that issue 3. Instead of Adding in Layout, Just Create one ViewGroup in Fragment and when onActivtyCreated called you can Add that layout runtime.
EDITED
I tried that sample, And I tried to add it in Fragment, Problem I faced is, Actually the CalendarView fragment is not attached even though our Fragment attached to the Activity, So as I Mentioned in Solution 3 that we can add it in onActivtyCreated
that is wrong.
Then how we can solve temporarily?
I solved by adding the view in onStart
(I know this is the wrong place this will call multiple time in the life cycle of Fragment), but we can add some logic and we can add this calendar view only once for making it work now till the dev fix in their lib.
My sample :
My fragment Layout:
<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>
Fragment code
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);
}
}
Note:
If you take above approach, Please add some logic and make sure it's not adding multiple time when onStart calls in the Fragment.