在ViewPager中的Fragment无法编辑ActionBar标题

9

我有一个单一的Activity,通过ViewPager托管多个片段。在Activity的onCreate方法中,我使用以下代码更改ActionBar标题:

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    if(getSupportActionBar() != null) {
        getSupportActionBar().setTitle(getResources().getString(R.string.custom_title));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

这个功能运行良好,但当Fragment变得可见后,我无法立即更改它。为了检测它,我已经实现了以下代码:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {

    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser && getContext() != null) {
            ((MainActivity) getContext()).editActionBarTitle("new title");
    }
}

以下是 editActionBarTitle 的定义:

public void editActionBarTitle(String title) {
     if(getSupportActionBar() != null) {
         getSupportActionBar().setTitle(title);
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
     }
}

我可以看到该方法在片段变得可见时被调用,但对ActionBar的标题没有影响。我错过了什么以便正确编辑标题?


编辑

我还尝试在viewPager中实现addOnPageChangeListener,我可以看到方法onPageSelected被调用,但对标题没有影响,在MainActivity中的示例如下:

public class MainActivity extends BaseActivity {   

    private NoScrollViewPager mViewPager;
    private SectionsPagerAdapter mAdapter;

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

        // Toolbar initialization
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        if(getSupportActionBar() != null) {
            getSupportActionBar().setTitle("MainActivity");
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        // ViewPager initialization
        mViewPager = findViewById(R.id.containter);
        setupViewPager();
    }

    private void setupViewPager() {

        mAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        mAdapter.addFragment(new Fragment1(), "Fragment 1");
        mAdapter.addFragment(new Fragment2(), "Fragment 2");
        mAdapter.addFragment(new Fragment3(), "Fragment 3");

        mViewPager.setOffscreenPageLimit(mAdapter.getCount());
        mViewPager.setAdapter(mAdapter);

        // viewPager event listener
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }

            @Override
            public void onPageSelected(int position) {
                setTitle("fragment " + position);
                if(getSupportActionBar() != null) {
                    getSupportActionBar().setTitle("fragment " + position);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) { }
        });
    }

    public void setViewPager(int position) { mViewPager.setCurrentItem(position); }
}

这是自定义的ViewPager类:
public class NoScrollViewPager extends ViewPager {

    // Disable horizontal scrolling in ViewPager
    private boolean isPagingEnabled = false;

    public NoScrollViewPager(Context context) {
        super(context);
    }

    public NoScrollViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    @SuppressLint("AndroidLintClickableViewAccessibility")
    public boolean onTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.isPagingEnabled && super.onInterceptTouchEvent(event);
    }

    public void setPagingEnabled(boolean b) {
        this.isPagingEnabled = b;
    }
}

这是自定义适配器类:

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    private FragmentManager fragmentManager;

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
        fragmentManager = fm;
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

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

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

    @Override
    public int getItemPosition(Object object) { return POSITION_NONE; }

}

尝试这个代码:((MainActivity)getActivity()).getSupportActionBar().setTitle(); - grabarz121
6个回答

7
在您的片段的onCreateView方法中尝试此方法。这可能会对您有所帮助。
if(getActivity() != null){
     getActivity().setTitle("Your title");
}

如果您在片段中使用了ViewPager,则可以使用以下代码:
@Override
    public void setUserVisibleHint(boolean isVisible) {
        super.setUserVisibleHint(isVisible);

        if (isVisible) {
            if(getActivity() != null){
               getActivity().setTitle("Your title");
            }
        }
    }

3
我不能在 onCreateView 中使用它,因为每个片段都在 ViewPager 中加载,所以该方法在我实例化 ViewPager 时就被调用了。这就是为什么我使用 setUserVisibleHint 来检测其中一个片段何时变为可见。 - LS_
1
只需将上面的代码放入您的 setUserVisibleHint 中即可正常工作。 - 113408
是的,如果您使用了ViewPager,则可以使用setUserVisibleHint来检测片段何时变为可见。 - Zakaria Hossain
感谢 @LS_,现在我已经将这个添加到我的答案中了。 - Zakaria Hossain

4

你还可以使用 viewPager.addOnPageChangeListener()

  • 添加一个侦听器,每当页面更改或逐步滚动时都会调用

viewPager.addOnPageChangeListener()中,你需要在onPageSelected()内设置标题到你的actionbar

onPageSelected()返回当前选定的页在viewpager

示例代码

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i1) {

        }

        @Override
        public void onPageSelected(int i) {

            if (i == 0) {
                getSupportActionBar().setTitle("Fragment One");
            } else if (i == 1) {
                getSupportActionBar().setTitle("Fragment Two");
            } else if (i == 2) {
                getSupportActionBar().setTitle("Fragment three");
            } else if (i == 3) {
                getSupportActionBar().setTitle("Fragment four");
            } else if (i == 4) {
                getSupportActionBar().setTitle("Fragment Five");
            }

        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }
    });

这是我使用的可行代码:

活动代码

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;


public class HomeActivity extends AppCompatActivity {


    private NoScrollViewPager mViewPager;
    private SectionsPagerAdapter mAdapter;


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

        // Toolbar initialization
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportActionBar().setTitle("Fragment One");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        // ViewPager initialization
        mViewPager = findViewById(R.id.containter);

        findViewById(R.id.btnOne).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewPager.setCurrentItem(0);
            }
        });
        findViewById(R.id.btnTwo).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewPager.setCurrentItem(1);
            }
        });
        findViewById(R.id.btnThree).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mViewPager.setCurrentItem(2);
            }
        });

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int i, float v, int i1) {

            }

            @Override
            public void onPageSelected(int i) {

                if (i == 0) {
                    getSupportActionBar().setTitle("Fragment One");
                } else if (i == 1) {
                    getSupportActionBar().setTitle("Fragment Two");
                } else if (i == 2) {
                    getSupportActionBar().setTitle("Fragment three");
                }

            }

            @Override
            public void onPageScrollStateChanged(int i) {

            }
        });


        setupViewPager();


    }

    private void setupViewPager() {

        mAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        mAdapter.addFragment(new Fragment1(), "Fragment 1");
        mAdapter.addFragment(new Fragment2(), "Fragment 2");
        mAdapter.addFragment(new Fragment3(), "Fragment 3");

        mViewPager.setOffscreenPageLimit(mAdapter.getCount());
        mViewPager.setAdapter(mAdapter);

        // viewPager event listener
    }


}

布局

<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnOne"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Frag 1" />

        <Button
            android:id="@+id/btnTwo"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Frag 2" />


        <Button
            android:id="@+id/btnThree"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Frag 3" />

    </LinearLayout>

    <neel.com.demo.NoScrollViewPager
        android:id="@+id/containter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

OUTPUT

https://www.youtube.com/watch?v=ytJogOkj1zQ


抱歉,我忘记提到我已经尝试使用 addOnPageChangeListener,但标题仍未更改。我已添加了一个代码示例,展示如何初始化 viewPager 和 adapter。 - LS_
@LS_ 你能分享你整个活动代码吗?如果可能的话,可以在Github上分享你的代码吗? - AskNilesh
我已经添加了一个Activity的示例,仅包含ViewPager和Adapter的自定义类以及相关代码。 - LS_
1
好的,我会尝试一下。顺便说一下,我会把赏金分配给你,因为这是对我来说最完整的答案。我仍然不确定我的问题可能是什么,但如果我找到解决方案,我会继续更新帖子。 - LS_
1
当然!再次感谢。 - LS_
显示剩余8条评论

1
唯一合法的理解方式是,FragmentAViewPager 中显示,是通过响应 OnPageChangeListener 回调函数实现的。
采用 这个答案 中提到的技术,你最终可能会得到以下代码:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageSelected(final int i) {
            MyAdapter adapter = ((MyAdapter) viewPager.getAdapter());
            TitleOwner titleOwner = adapter.getTitleOwner(index);
            String title = titleOwner.getTitle();
            getSupportActionBar().setTitle(title);
        }

        @Override
        public void onPageScrollStateChanged(final int i) {
        }

        @Override
        public void onPageScrolled(final int i,final float v,final int i1) {
        }
});

假设所有在 ViewPager 中显示的片段都实现了 TitleOwner:
interface TitleOwner {
    String getTitle();
}

和片段类:

class MainScreenFragment extends Fragment implements TitleOwner {
    ...
    @Override
    public String getTitle() {
        return "Main Screen";
    }
}

0

我在最近的一个项目中遇到了这个问题。最终我为每个片段设计了独立的工具栏,每个工具栏都有自己的标题。我使用了:

Theme.MaterialComponents.NoActionBar

0

将 onPageSelected 中的代码更改为

setTitle("fragment " + position);
if(getSupportActionBar() != null) {
    getSupportActionBar().setTitle("fragment " + position);
}

到这里

toolbar.setTitle(title);

继承AppCompatActivity而不是BaseActivity。 在onCreate中保持相同的代码


0

请检查您是否正在使用NoActionBar主题。例如Theme.AppCompat.Light.NoActionBarTheme.MaterialComponents.NoActionBar


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接