java - 如何在布局内部绘制布局

标签 java android xml layout android-viewtreeobserver

我有一个应用程序,在单击“统计”后我调用 StatsFragment。 StatsFragment 使用fragment_stats xml 布局,其中有TabLayout 和CustomViewPager。但是,当我单击“统计”时,我的 StatsFragment 被称为数据,但不会在那里绘制。当我点击一些选项卡后,数据就会出现。 问题出在初始绘图上。来自 How can you tell when a layout has been drawn?我知道我会以某种方式使用 ViewTreeObserver,但找不到方法和方式。

fragment_stats xml 文件:

<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 文件:

<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 文件:

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);
}
}

最佳答案

据我所知,您没有在正确的时间做正确的事情。 当调用 fragment 的 onCreateView 时,您会膨胀相应的布局,但不会在其中设置任何值。

只需将 onActivityCreated 中的所有代码交换到 onCreateView 中即可解决问题,如下所示:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

 // Inflate the layout for this fragment
 View layout = inflater.inflate(R.layout.fragment_stats, container, false);
TabLayout tabLayout = (TabLayout)layout.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) layout.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());
processChanges((adapter.getItem(tab.getPosition())).getView(),tab.getPosition());
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
    }
    });
return (layout);
}

编辑:在第二次(更仔细地)查看您的代码后,最好的想法是让 fragment 管理您的选项卡,以便您可以将逻辑放在那里(并将它们放置在每个选项卡中)。为此:

第 1 步:为您的页面创建一个新的 fragment 类

public abstract class PageFragment extends Fragment {
  private int pageNumber;
  public static PageFragment newInstance(int page) {
    Bundle args = new Bundle();
    args.putInt("page_number", page);
    PageFragment fragment = new PageFragment();
    fragment.setArguments(args);
    return (fragment);
  }
  public PageFragment(){}
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
      pageNumber = getArguments().getInt("page_number");
    }
  }
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View layout = inflater.inflate(R.layout.tab_fragment, container, false);
    //Get all the views you need for your page, using 
    //layout.findViewById();

    //Then you will need to call processChanges for that page
    processChanges(layout, pageNumber);
    return (layout);
  }
  //Also add here all the logic associated with processChanges
}

第 2 步是在 StatsFragment 中获取 fragment 的引用,并将这些 fragment 添加到寻呼机中:

private PageFragment pageOne;
private PageFragment pageTwo;
private PageFragment pageThree;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

 // Inflate the layout for this fragment
 View layout = inflater.inflate(R.layout.fragment_stats, container, false);
 TabLayout tabLayout = (TabLayout)layout.findViewById(R.id.tab_layout);
 pageOne = PageFragment.newInstance(0);
 pageTwo = PageFragment.newInstance(1);
 pageThree = PageFragment.newInstance(2);

 tabLayout.addFragment(pageOne, "7 days");
 tabLayout.addFragment(pageTwo, "1 month");
 tabLayout.addFragment(pageThree, "1 year");
 tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
}

第 3 步:您最终需要一个自定义寻呼机适配器来保存寻呼机的标题和 fragment :

public class MyViewPagerAdapter extends FragmentPagerAdapter {
  private List<Fragment> mFragments = new ArrayList<>();
  private List<String> mTitles = new ArrayList<>();

  public MyViewPagerAdapter(FragmentManager fm) {
      super(fm);
  }

  public void addFragment(Fragment fragment, String title) {
      mFragments.add(fragment);
      mTitles.add(title);
  }

  @Override
  public Fragment getItem(int position) {
      return (mFragments.get(position));
  }

  @Override
  public int getCount() {
      return (mFragments.size());
  }

  @Override
  public String getPageTitle(int position) {
      return (mTitles.get(position));
  }
}

要使用它,只需通过(而不是您的 PagerAdapter)创建它

final MyPagerAdapter adapter = new MyPagerAdapter(getActivity().getSupportFragmentManager());

关于java - 如何在布局内部绘制布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37696647/

相关文章:

javascript - 初始切换后,侧边栏停止在 Android Chrome 上显示

android - 如何检查 Android 服务是否已在运行

java - JAXB 有没有办法根据读入的 xml 文件中的顺序编码新的 xml?

xml - 使用 XSLT 根据属性合并 Xml 元素

python - 使用 ElementTree 解析 XML 文件的一部分时遇到困难

java - Mockk - 模拟实现多个接口(interface)的最终类​​时出现 ClassCastException

Java keytool/用java生成 key 的安全性(一般)

Android - 使用按钮控制 fragment 内的 ListView

java - 用一个错误命名的字段使 MongoDB 崩溃,它有什么特别之处?

java - 密码正则表达式至少 8 个字符,包含字母数字/特殊字符