Java 为什么Android材质设计选项卡布局不起作用?

Java 为什么Android材质设计选项卡布局不起作用?,java,android,android-studio,gradle,sdk,Java,Android,Android Studio,Gradle,Sdk,我正在尝试使用viewpager创建表格布局,但它不起作用。通过tabLayout.setupWithViewPager(viewPager)加载时在PatientMain活动类中,输出为: 当我使用viewPager.addOnPageChangeListener(新建TabLayout.TabLayoutOnPageChangeListener(TabLayout))在PatientMain活动类中,输出为: 但是没有显示片段,也没有可用的滑动 我照章办事,正如人们所说的那样。我使用了一

我正在尝试使用viewpager创建表格布局,但它不起作用。通过
tabLayout.setupWithViewPager(viewPager)加载时在PatientMain活动类中,输出为:

当我使用
viewPager.addOnPageChangeListener(新建TabLayout.TabLayoutOnPageChangeListener(TabLayout))在PatientMain活动类中,输出为:

但是没有显示片段,也没有可用的滑动

我照章办事,正如人们所说的那样。我使用了一些源代码,比如,。我个人认为代码可能不是问题所在,所使用的sdk版本有问题,但我可能错了。这是我的密码:

主要活动:

package parsa.lop.adjust;

import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TabHost;

public class PatientMain extends AppCompatActivity {

    private TabHost tabHost;

    private TabLayout tabLayout;
    private ViewPager viewPager;
    private ViewPagerAdapter viewPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_patient_main);

        tabLayout = (TabLayout)findViewById(R.id.tabLayout);
        viewPager = (ViewPager)findViewById(R.id.viewPager);

        viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPagerAdapter.addFragment(new MyDietFragment(), "My Diet"); // `new MyDietFragment()` should be in `FragmentPagerAdapter.getItem()`
        viewPagerAdapter.addFragment(new MyWorkoutFragment(), "My Workout");  // `new MyWorkoutFragment()` should be in `FragmentPagerAdapter.getItem()`
        viewPagerAdapter.addFragment(new StartProgramFragment(), "Start a Program");  // `new StartProgramFragment()` should be in `FragmentPagerAdapter.getItem()`
        viewPager.setAdapter(viewPagerAdapter);



        final TabLayout.Tab myDietTab = tabLayout.newTab();
        final TabLayout.Tab myWorkOutTab = tabLayout.newTab();
        final TabLayout.Tab startProgramTab = tabLayout.newTab();

        myDietTab.setText("My Diet");
        myWorkOutTab.setText("My Workout");
        startProgramTab.setText("Start a Program");

        tabLayout.addTab(startProgramTab,0);
        tabLayout.addTab(myDietTab,1);
        tabLayout.addTab(myWorkOutTab,2);

//        tabLayout.setupWithViewPager(viewPager);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

    }
}
android:theme="@style/AppTheme.NoActionBar"
ViewPager适配器:

package parsa.lop.adjust;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;

import java.util.ArrayList;
import java.util.List;

public class ViewPagerAdapter extends FragmentPagerAdapter {

    private List<String> fragmentTitleList = new ArrayList<String>();
    private List<Fragment> fragmentList = new ArrayList<Fragment>(); // this line can cause crashes

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

    @Override
    public Fragment getItem(int position) {
        return fragmentList.get(position); // viewPager fragments should be created here
    }

    @Override
    public int getCount() {
        return 0; // this is the bug :p
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return fragmentTitleList.get(position);
    }

    public void addFragment(Fragment fragment, String title){
        fragmentList.add(fragment); // this line can cause crashes
        fragmentTitleList.add(title);
    }
}
我的主要布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".PatientMain">

    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:background="@color/colorPrimary"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true">

    </android.support.design.widget.TabLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>

</android.support.constraint.ConstraintLayout>

在ViewPagerAdapter中,替换以下内容:

@Override 
public int getCount() { 
    return 0; 
}
为此:

@Override 
public int getCount() {
    return fragmentList.size();
}
您正在将适配器内容的计数设置为0,这与适配器告诉其他组件它没有要显示的项相同



此外,您应该确保由ViewPager承载的片段是在FragmentPagerAdapter.getItem()中创建的,而不是在活动中创建的。

在ViewPagerAdapter中,替换以下内容:

@Override 
public int getCount() { 
    return 0; 
}
为此:

@Override 
public int getCount() {
    return fragmentList.size();
}
您正在将适配器内容的计数设置为0,这与适配器告诉其他组件它没有要显示的项相同



此外,您应该确保ViewPager承载的片段是在FragmentPagerAdapter.getItem()中创建的,而不是在活动中创建的。

您还应该取消注释:

tabLayout.setupWithViewPager(viewPager);
记住,使用此实现,您的ViewPager将每隔2次滑动距离重新构建其中的片段。我的意思是:如果你有3个碎片,从1开始你在2上滑动到2,它将重新创建第3个碎片,如果从3开始你在2上滑动到1,它将重新创建第一个碎片(无论你是否已经创建了碎片,它都会这样做)。 为了避免此问题(如果您需要不重新创建片段),您应该使用:

viewPager.setOffscreenPageLimit(<num_of_your_pages>)
此外,您使用的代码:

final TabLayout.Tab myDietTab = tabLayout.newTab();
        final TabLayout.Tab myWorkOutTab = tabLayout.newTab();
        final TabLayout.Tab startProgramTab = tabLayout.newTab();

        myDietTab.setText("My Diet");
        myWorkOutTab.setText("My Workout");
        startProgramTab.setText("Start a Program");
是无用的,因为在将片段添加到viewPager时,您已经定义了片段的标题。所以你应该加上:

@Override
public CharSequence getPageTitle(int position) {
    return mFragmentTitleList.get(position);
}

/** Public Methods **/
    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment); // this line can cause crashes
        mFragmentTitleList.add(title);
    }
对于您的ViewPager,您将通过这种方式为其设置片段和标题。 然后使用: tabLayout.setupWithViewPager(viewPager)

另外,您不应该使用构造函数实例化片段,而应该使用静态工厂方法(如果您需要将值传递给片段,这很有用)。 静态工厂方法是一种调用构造函数来实例化对象实例的方法,然后它可以对其执行一些操作(在片段的情况下,它将设置一个参数束,将属性传递给片段的onCreate方法,该方法将获取参数并设置自身的属性)。 片段初始化示例:

public static void initInstance(int myVal1, int myVal2){
     MyFragment mInstance = new MyFragment();
     Bundle args = new Bundle();
     args.putInt(<BUNDLE_KEY_MYVAL1>, myVal1);
     args.putInt(<BUNDLE_KEY_MYVAL2>, myVal2);
     mInstance.setArguments(args);
     return mInstance;
}
publicstaticvoidinitinstance(int-myVal1,int-myVal2){
MyFragment MinInstance=新的MyFragment();
Bundle args=新Bundle();
参数putInt(,myVal1);
参数putInt(,myVal2);
mInstance.setArguments(args);
回报率;
}
最后,我建议迁移到androidx,因为支持库将不再更新(:


希望这有帮助:D有一个很好的编码!

您还应该取消注释:

tabLayout.setupWithViewPager(viewPager);
记住,在这个实现中,您的ViewPager将每隔2次滑动距离重新构建其中的片段。我的意思是:如果您有3个片段,从1滑动到2对2,它将重新创建第3个片段,如果从3滑动到1对2,它将重新创建第一个片段(无论您是否已经创建了片段,它都将始终执行此操作)。 为了避免此问题(如果您需要不重新创建片段),您应该使用:

viewPager.setOffscreenPageLimit(<num_of_your_pages>)
此外,您使用的代码:

final TabLayout.Tab myDietTab = tabLayout.newTab();
        final TabLayout.Tab myWorkOutTab = tabLayout.newTab();
        final TabLayout.Tab startProgramTab = tabLayout.newTab();

        myDietTab.setText("My Diet");
        myWorkOutTab.setText("My Workout");
        startProgramTab.setText("Start a Program");
是无用的,因为在将片段添加到viewPager时,您已经定义了片段的标题。因此,您应该添加:

@Override
public CharSequence getPageTitle(int position) {
    return mFragmentTitleList.get(position);
}

/** Public Methods **/
    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment); // this line can cause crashes
        mFragmentTitleList.add(title);
    }
对于您的ViewPager,您将通过这种方式为其设置片段和标题。 然后使用: tabLayout.setupWithViewPager(viewPager)

另外,您不应该使用构造函数实例化片段,而应该使用静态工厂方法(如果您需要将值传递给片段,这很有用)。 静态工厂方法是一种调用构造函数来实例化对象实例的方法,然后它可以对其执行一些操作(在片段的情况下,它将设置一个参数束,将属性传递给片段的onCreate方法,该方法将获取参数并设置自身的属性)。 片段初始化示例:

public static void initInstance(int myVal1, int myVal2){
     MyFragment mInstance = new MyFragment();
     Bundle args = new Bundle();
     args.putInt(<BUNDLE_KEY_MYVAL1>, myVal1);
     args.putInt(<BUNDLE_KEY_MYVAL2>, myVal2);
     mInstance.setArguments(args);
     return mInstance;
}
publicstaticvoidinitinstance(int-myVal1,int-myVal2){
MyFragment MinInstance=新的MyFragment();
Bundle args=新Bundle();
参数putInt(,myVal1);
参数putInt(,myVal2);
mInstance.setArguments(args);
回报率;
}
最后,我建议迁移到androidx,因为支持库将不再更新(:

希望这是有帮助的:D有一个很好的编码