I have aplication where after clicking on Statistics i call StatsFragment. StatsFragment uses fragment_stats xml layout that has there a TabLayout and CustomViewPager. However when i clicked on Statistics so my StatsFragment is called data are not drawn there. After i click on some tab data will be there. Problem is with initial drawing. From How can you tell when a layout has been drawn? i know i shall use somehow ViewTreeObserver but cant find the way where and how.
fragment_stats xml file:
<RelativeLayout 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=".StatsFragment">
<!-- TODO: Update blank fragment layout -->
<!--android:elevation="6dp"-->
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
/>
<pv239.fi.muni.cz.moneymanager.CustomViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_below="@id/tab_layout"
>
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:textColor="#fff"
android:paddingTop="4dp"
android:paddingBottom="4dp" />
</pv239.fi.muni.cz.moneymanager.CustomViewPager>
</RelativeLayout>
tab_fragment xml file:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:id="@+id/gridViewScreenStats">
<com.jjoe64.graphview.GraphView
android:layout_width="match_parent"
android:layout_height="200dp"
android:id="@+id/graph" />
<GridLayout
android:id="@+id/stats"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/graph"
android:layout_gravity="center"
android:background="@drawable/box"
android:layout_margin="10dp"
android:rowCount="5"
android:columnCount="2"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Starting balance: "
android:paddingLeft="10dp"
android:id="@+id/startBalanceLabel"
android:layout_row="0"
android:layout_column="0"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/startBalanceLabel"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:id="@+id/startBalance"
android:layout_row="0"
android:layout_column="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/startBalance"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Ending balance: "
android:paddingLeft="10dp"
android:id="@+id/endBalanceLabel"
android:layout_row="1"
android:layout_column="0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/startBalance"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:layout_toRightOf="@id/endBalanceLabel"
android:id="@+id/endBalance"
android:layout_row="1"
android:layout_column="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Incomes: "
android:layout_below="@id/endBalanceLabel"
android:id="@+id/incomeStats"
android:layout_row="2"
android:layout_column="0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:textColor="@color/recordPositiveValue"
android:id="@+id/incomeSumStats"
android:layout_below="@id/endBalance"
android:textAlignment="textEnd"
android:layout_row="2"
android:layout_column="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Expenses:"
android:id="@+id/expenseStats"
android:layout_row="3"
android:layout_column="0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:textColor="@color/recordNegativeValue"
android:id="@+id/expenseSumStats"
android:textAlignment="textEnd"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_row="3"
android:layout_column="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="+/- status:"
android:id="@+id/actualStats"
android:layout_row="4"
android:layout_column="0" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=""
android:id="@+id/actualSumStats"
android:textColor="@color/recordPositiveValue"
android:textAlignment="textEnd"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_row="4"
android:layout_column="1" />
</GridLayout>
<!-- Income records -->
<ListView
android:layout_width="wrap_content"
android:layout_height="300dp"
android:background="@drawable/box"
android:layout_below="@id/stats"
android:layout_margin="10dp"
android:id="@+id/listViewIncomeStats"
android:nestedScrollingEnabled="true"/>
<!-- Expenses records -->
<ListView
android:layout_width="wrap_content"
android:layout_height="300dp"
android:background="@drawable/box"
android:layout_below="@+id/listViewIncomeStats"
android:layout_margin="10dp"
android:id="@+id/listViewExpences"
android:nestedScrollingEnabled="true"/>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
StatsFragment java file:
public class StatsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private ListView incomeListView;
private ListView expensesListView;
private OnStatsInteractionListener mListener;
public StatsFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment StatsFragment.
*/
// TODO: Rename and change types and number of parameters
public static StatsFragment newInstance(String param1, String param2) {
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
StatsFragment fragment = new StatsFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_stats, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TabLayout tabLayout = (TabLayout) getView().findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("7 days"));
tabLayout.addTab(tabLayout.newTab().setText("1 month"));
tabLayout.addTab(tabLayout.newTab().setText("1 year"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final CustomViewPager viewPager = (CustomViewPager) getView().findViewById(R.id.pager);
final PagerAdapter adapter = new PagerAdapter(getActivity().getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.setPagingEnabled(false);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
// TextView txt = (TextView) (adapter.getItem(tab.getPosition())).getView().findViewById(R.id.startMonthStats);
processChanges((adapter.getItem(tab.getPosition())).getView(),tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onStatsInteraction(uri);
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnStatsInteractionListener {
// TODO: Update argument type and name
void onStatsInteraction(Uri uri);
}
private Date numbersToDate(int daysBack, int monthsBack, int yearsBack)
{
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR, daysBack *(-1));
cal.add(Calendar.MONTH, monthsBack *(-1));
cal.add(Calendar.YEAR, yearsBack *(-1));
return cal.getTime();
}
public void processChanges(View tabView, int tabNum)
{
int d =7;
int m =0;
int y =0;
MMDatabaseHelper sloh = MMDatabaseHelper.getInstance(getActivity());
if (tabNum == 1)
{
d =0;
m =1;
y =0;
}
else if (tabNum == 2)
{
d =0;
m =0;
y =1;
}
createGraph(tabView, d, m, y, sloh);
setBalances(tabView, d, m, y, sloh);
setListValues(tabView, d, m, y, sloh);
}
private void setListValues(View tabView, int d, int m, int y,MMDatabaseHelper sloh) {
// Creating incomes list
incomeListView = (ListView) tabView.findViewById(R.id.listViewIncomeStats);
Cursor incomeRecords = sloh.getRecordsInRange(">",d,m,y);
RecordsDbToStatsAdapter incomeAdapter = new RecordsDbToStatsAdapter(this.getContext(), incomeRecords, 0);
incomeListView.setAdapter(incomeAdapter);
// Creating expenses list
expensesListView = (ListView) tabView.findViewById(R.id.listViewExpences);
Cursor expensesRecords = sloh.getRecordsInRange("<",d,m,y);
RecordsDbToStatsAdapter expensesAdapter = new RecordsDbToStatsAdapter(this.getContext(), expensesRecords, 0);
expensesListView.setAdapter(expensesAdapter);
}
private void setBalances(View tabView, int d, int m, int y, MMDatabaseHelper sloh) {
//Fetching Values of incomes and expenses and balances
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.getDefault());
format.setMaximumFractionDigits(2);
TextView incSum = (TextView) tabView.findViewById(R.id.incomeSumStats);
Integer helpInc = sloh.getSumRecordsInRange(">",d,m,y);
BigDecimal incValue = new BigDecimal(helpInc.toString());
incSum.setText(format.format(incValue.abs().setScale(2).doubleValue()));
TextView expSum = (TextView) tabView.findViewById(R.id.expenseSumStats);
Integer helpExp = sloh.getSumRecordsInRange("<",d,m,y);
BigDecimal expValue = new BigDecimal(helpExp.toString());
expSum.setText(format.format(expValue.abs().setScale(2).doubleValue()));
TextView startBal = (TextView) tabView.findViewById(R.id.startBalance);
BigDecimal startValue = new BigDecimal(sloh.getStartingBal(numbersToDate(d,m,y)).toString());
startBal.setText(format.format(startValue.abs().setScale(2).doubleValue()));
TextView endBal = (TextView) tabView.findViewById(R.id.endBalance);
BigDecimal endValue = new BigDecimal(sloh.getEndingBal().toString());
endBal.setText(format.format(endValue.abs().setScale(2).doubleValue()));
TextView actState = (TextView) tabView.findViewById(R.id.actualSumStats);
actState.setText(format.format(new BigDecimal(helpInc + helpExp).setScale(2).doubleValue()));
}
private void createGraph(View tabView, int d, int m, int y, MMDatabaseHelper sloh) {
// Graph rendering section
// Cursor graphCursor = sloh.getRecordsInRange(null,d,m,y);
// graphCursor.moveToFirst();
int days=0;
if (d == 7) { days = d;}
if (m == 1) { days = 28;}
if (y == 1) { days = 365;}
ArrayList numList = new ArrayList();
GraphView graph = (GraphView) tabView.findViewById(R.id.graph);
LineGraphSeries<DataPoint> series = new LineGraphSeries<DataPoint>(new DataPoint[] { });
Calendar day = Calendar.getInstance();
day.set(Calendar.HOUR_OF_DAY,0);
day.set(Calendar.MINUTE,0);
day.set(Calendar.SECOND,0);
for(int i=days; i>0;i--) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_YEAR,-i);
day.setTime(cal.getTime());
Log.i("TIME",cal.getTime().toString());
numList.add(sloh.getCurrentBalanceForOneDay(cal.getTime()));
series.appendData(new DataPoint(day.getTime(),sloh.getCurrentBalanceForOneDay(cal.getTime())),true,days);
}
Log.i("Pole", numList.toString());
graph.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(getActivity()));
graph.getGridLabelRenderer().setNumHorizontalLabels(4); // only 4 because of the space
graph.addSeries(series);
}
}
From what I can tell, you're not doing the right things at the right time. When the
onCreateViewof your fragment is called, you inflate the corresponding layout but do not set any value in there.Simply swapping all the code you have in
onActivityCreatedinto theonCreateViewshould do the trick, as follow :EDIT : After having a second (and closer) look at your code, the best idea would be to have fragments managing your tabs, so that you could put your logic in there (and place them in each tab). To do so :
Step 1 : Create a new fragment class for your pages
Step 2 will be to get references of your fragments in your StatsFragment, and add these fragments to your pager :
Step 3 : You will finally need to have a custom pager adapter to hold the titles and the fragments of your pager :
To use it, simply create it via (instead of your
PagerAdapter)