具有自定义 tablayout 的 ViewPager2

ViewPager2 with custom tablayout

我开始使用 ViewPager2,但我不知道如何使用自定义 tablayout 将页面标题自定义为普通 viewpager。

我找到了一个临时的好办法。

1-对选项卡使用 RecyclerView 并手动处理。

2-对片段使用 ViewPager2。

public class ViewPagerHelper extends ViewPager2.OnPageChangeCallback implements TabSelectInterface {
    private Activity activity;
    private byte from;
    private RecyclerView recyclerViewTabs;
    private ViewPager2 viewPager2;
    private List<Fragment> fragmentList;
    private List<String> tabList;
    private ViewPagerTabsAdapter viewPagerTabsAdapter;
    private FragmentManager fragmentManager;
    private boolean isLive;
    private LinearLayoutManager linearLayoutManagerTabs;

    public ViewPagerHelper(FragmentManager fragmentManager, Activity activity, byte from, List<Fragment> fragmentList, List<String> tabList, boolean isLive) {
        this.fragmentManager = fragmentManager;
        this.activity = activity;
        this.from = from;
        this.fragmentList = fragmentList;
        this.tabList = tabList;
        this.isLive = isLive;
        setupViewPager();

    }

    private void setupViewPager() {
        recyclerViewTabs = activity.findViewById(R.id.recycle_tabs);
        viewPager2 = activity.findViewById(R.id.viewpager);


        linearLayoutManagerTabs = new LinearLayoutManager(activity, RecyclerView.HORIZONTAL, false);

        recyclerViewTabs.setLayoutManager(linearLayoutManagerTabs);


        setTabsAdapter();
        setFragmentsAdapter();


        viewPager2.registerOnPageChangeCallback(this);


//        viewPager2.setUserInputEnabled(false);
    }


    private void setTabsAdapter() {
        viewPagerTabsAdapter = new ViewPagerTabsAdapter(activity, tabList, isLive, this);
        recyclerViewTabs.setAdapter(viewPagerTabsAdapter);
    }

    private void setFragmentsAdapter() {
        ViewPagerFragmentAdapter viewPagerFragmentAdapter = new ViewPagerFragmentAdapter(fragmentManager, fragmentList);
        viewPager2.setAdapter(viewPagerFragmentAdapter);
    }


    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        System.out.println("onPageScrolled1: " + position);
        System.out.println("onPageScrolled2: " + positionOffset);
        System.out.println("onPageScrolled3: " + positionOffsetPixels);
        super.onPageScrolled(position, positionOffset, positionOffsetPixels);
    }

    @Override
    public void onPageSelected(int position) {
        super.onPageSelected(position);

        Log.e("Selected_Page", String.valueOf(position));
        viewPagerTabsAdapter.setSelectedTab(position);
        linearLayoutManagerTabs.scrollToPositionWithOffset(position, 0);
    }

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

    @Override
    public void onTabSelected(int position) {
        viewPager2.setCurrentItem(position, true);
    }


    public void animateFirstTab(){
        viewPagerTabsAdapter.animateFirstTab();
    }

和 viewpager2 适配器 class

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

    private List<Fragment> arrayList;

    ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, List<Fragment> arrayList) {
        super(fragmentManager);
        this.arrayList = arrayList;
    }

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


    @Override
    public int getItemCount() {
        return arrayList.size();
    }


}

recyclerview 选项卡适配器

public class ViewPagerTabsAdapter extends RecyclerView.Adapter<ViewPagerTabsAdapter.OrderHolder> {
    private Context context;
    private List<String> list;
    private int selectedTab = 0;
    private TabSelectInterface tabSelectInterface;
    private boolean isLive = false;

    private List<Integer> tabsWidth = new ArrayList<>();
    int numberToSpliteWidth = 0;
private boolean animateFirstTab=false;
    ViewPagerTabsAdapter(Context context, List<String> list, boolean isLive, TabSelectInterface tabSelectInterface) {
        this.context = context;
        this.list = list;
        this.isLive = isLive;
        this.tabSelectInterface = tabSelectInterface;
    }

    @NonNull
    @Override
    public OrderHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View rowView = LayoutInflater.from(context).inflate(R.layout.custom_tab, parent, false);
//        final RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(rowView);

//        if (!tabsWidth.isEmpty()) {
//            int sumWidths = 0;
//            for (Integer w : tabsWidth) {
//                sumWidths += w;
//            }
//
//            //no scroll needed, split the width
//            if (sumWidths < parent.getWidth()) {
//
//                System.out.println("THEWIDTHIS: " + viewType);
//                int newWidth = parent.getWidth() / list.size();
//                if (newWidth > viewType) {
//                    rowView.getLayoutParams().width = newWidth;
//                }
//
//
//            }
//
//        }

        if (!tabsWidth.isEmpty()) {

        DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
        int newTabMinWidth = displayMetrics.widthPixels / list.size();
        System.out.println("THEtabMinWidth: " + newTabMinWidth);
        if (list.size() <= 4) {
//            rowView.setMinimumWidth(tabMinWidth - 25);
            if (newTabMinWidth > viewType) {
                rowView.getLayoutParams().width = newTabMinWidth;
            }
        } else {
//            rowView.setMinimumWidth(tabMinWidth + 32);
            if (newTabMinWidth > viewType) {
                rowView.getLayoutParams().width = (int) (newTabMinWidth + context.getResources().getDimension(R.dimen._9sdp));
            }
        }
        }
        return new OrderHolder(rowView);
    }

    @Override
    public void onBindViewHolder(@NonNull OrderHolder holder, int position) {
        holder.name.setText(list.get(position));
        if (selectedTab == position) {
            holder.name.setTextColor(ContextCompat.getColor(context, R.color.yellow));
            holder.selectedView.setVisibility(View.VISIBLE);
        } else {
            holder.name.setTextColor(ContextCompat.getColor(context, R.color.font2));
            holder.selectedView.setVisibility(View.INVISIBLE);
        }

        if (holder.name.getText().toString().equals("الفيديو")) {
//
            if (isLive) {
                Glide.with(context).asGif().load(R.drawable.live).into(holder.imageView);
                holder.imgframe.setVisibility(View.VISIBLE);
            } else {
                holder.imgframe.setVisibility(View.GONE);

            }
        } else {
            holder.imgframe.setVisibility(View.GONE);

        }


        if (animateFirstTab){

            Animation a = AnimationUtils.loadAnimation(context, R.anim.scale);
            a.reset();
            holder.name.clearAnimation();
            holder.name.startAnimation(a);
            animateFirstTab=false;




        }

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tabSelectInterface.onTabSelected(holder.getAdapterPosition());
            }
        });

        if (tabsWidth.isEmpty()) {

            final ViewTreeObserver observer = holder.itemView.getViewTreeObserver();
            observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    holder.itemView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

//                    int containerWidth = holder.itemView.getWidth();
//                    int containerHeight = holder.itemView.getHeight();
//                    float x = containerWidth - Float.parseFloat(model.getXpoints(o)) / 100 * containerWidth;
//                    float y = containerHeight - Float.parseFloat(model.getYpoints(o)) / 100 * containerHeight;
//                    Log.e("measuredWidth", "" + containerHeight + "" + containerWidth);
//                    Log.e("getPointX", "" + model.getXpoints(o) + "" + model.getYpoints(o));
//                    Log.e("x", "x" + x + "y" + y);
//
//                    h.tag.setX(x);
//                    h.tag.setY(y);
//                    h.tag.requestLayout();
                    System.out.println("THEWIDTHIS2: " + holder.itemView.getWidth());
                    tabsWidth.add(holder.itemView.getWidth());
                    if (position == list.size() - 1) {
                        System.out.println("notifiNOW");
                        notifyDataSetChanged();
                    }
                }
            });


        }




    }


    @Override
    public int getItemViewType(int position) {

        try {
            return tabsWidth.get(position);

        } catch (Exception e) {
//        return super.getItemViewType(position);
            return 0;
        }

    }


    @Override
    public int getItemCount() {
        return list.size();
    }


    void setSelectedTab(int selectedTab) {
        int currentSelectedTab = this.selectedTab;

        if (currentSelectedTab != selectedTab) {
            this.selectedTab = selectedTab;
            notifyItemChanged(currentSelectedTab);
            notifyItemChanged(selectedTab);
        }

    }

    void animateFirstTab() {
    animateFirstTab=true;
    notifyItemChanged(0);

    }


    public class OrderHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        private TextView name;
        private View selectedView;
        private FrameLayout imgframe;
        private ImageView imageView;


        OrderHolder(View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.textview);
            selectedView = itemView.findViewById(R.id.selected_view);

            imgframe = (FrameLayout) itemView.findViewById(R.id.imgframe);
            imageView = (ImageView) itemView.findViewById(R.id.imageView);

        }

        @Override
        public void onClick(View view) {

        }
    }

在 XML

中使用它
<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycle_tabs"
            android:layout_width="match_parent"
            android:layout_height="52dp"
            android:layout_gravity="center_horizontal"
            ads:layout_constraintBottom_toBottomOf="parent"
            ads:layout_constraintEnd_toEndOf="parent"
            ads:layout_constraintStart_toStartOf="parent" />



    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/container"
        android:layout_marginBottom="50dp" />

并使用它。你只需要使用这个代码

  List<Fragment> fragmentList = new ArrayList<>();
            List<String> tabtList = new ArrayList<>();

         tabtList.add(tab_index,"tab_name" );
                fragmentList.add(tab_index, new TabFragment());


  new ViewPagerHelper(getSupportFragmentManager(), MatchProfileActivity.this, VIEWPAGER_TYPE_FROM_MATCHES, fragmentList, tabtList,
                  false);

Hint: not all code needed I put all my code.

今天,我正在寻找这个东西。经过一些研究,一些尝试和错误,我想出了一个解决方案:

  1. 创建您的 xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/storiesTabLayout"
        app:layout_constraintTop_toTopOf="parent"
        android:clipToPadding="false"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/reactionsViewPager2"
        app:layout_constraintTop_toBottomOf="@id/storiesTabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>

现在为您的 viewPager2 创建一个适配器(我将使用 Recyclerview.Adapter,因为我不需要片段)。 现在你需要一个

  public fun getCustomTabAt(position: Int): View {
    val simpleStoryView: View = LayoutInflater.from(activity).inflate(R.layout.fragment_viewstoryreacts_simple_story_view, null);
    val roundedImageView: RoundedImageView = simpleStoryView.findViewById(R.id.storyImageView);
    var url = "";
    if(stories[position].getMedia().type == "photos") {
      url = stories[position].getMedia().data[0].url;
    }else{
      url = stories[position].getMedia().data[0].thumbnail?: "";
    }
    Picasso.get().load(url).into(roundedImageView);
    return simpleStoryView;
  }

Place it in your fragment/activity/adapter(我把它放在adapter中是为了方便,比如方便与数据集成)。基本上,此方法会创建并 returns 一个将显示在您的选项卡中的自定​​义视图。

最后,在您的 Fragment/activity 中,您需要这样的东西:

  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    fragmentRootView = inflater.inflate(R.layout.fragment_viewstoryreacts_bottomsheet, container, false);
    this.activity = requireActivity() as ConversationsActivity;
    initGui();
    return fragmentRootView;
  }

  /** Private methods */
  private fun initGui() {
    this.storiesTabLayout = fragmentRootView.findViewById(R.id.storiesTabLayout); 
// <--- Step 1: link the tab layout
    this.reactionsViewPager2 = fragmentRootView.findViewById(R.id.reactionsViewPager2);  
// step 2: link the viewPager2, and init adapters, data etc

    this.reactionsAdapter = ReactionsAdapter(activity = requireActivity(),stories = stories);

    reactionsViewPager2.adapter = reactionsAdapter;
    reactionsViewPager2.orientation = ViewPager2.ORIENTATION_HORIZONTAL;

    storiesTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
    storiesTabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);

// step3: init tabLayoutMediator to bind tabs with the viewPager2
    val tabLayoutMediator: TabLayoutMediator = TabLayoutMediator(storiesTabLayout, reactionsViewPager2, object : TabLayoutMediator.TabConfigurationStrategy{
      override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
        val finalPosition = position;
        val simpleStoryView: View = reactionsAdapter.getCustomTabAt(finalPosition);
        tab.customView = simpleStoryView;
      }
    });
    tabLayoutMediator.attach();  
// <-- step 4: call the attach()
  }

这是针对片段的。如果您正在使用 activity,只需在 onCreate() 方法中调用 initGui()

我们在这里创建一个 最后,运行 代码。这是我的输出:

如您所见,选项卡现在具有图像视图。 (viewpager2 需要一些工作)。 希望对您有所帮助。

        if (binding.buttonChat.tag == "unselected") {
            binding.buttonChat.setBackgroundResource(R.drawable.selected_button)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                context?.getColor(R.color.white)?.let { it1 ->
                    binding.buttonChat.setTextColor(
                        it1
                    )
                }
                context?.getColor(R.color.unselecdet_textXolor)?.let { it1 ->
                    binding.buttonGroup.setTextColor(
                        it1
                    )
                }
            } else {
                //noinspection deprecation
                context?.resources?.getColor(R.color.white)?.let { it1 ->
                    binding.buttonChat.setTextColor(
                        it1
                    )
                }
                context?.resources?.getColor(R.color.unselecdet_textXolor)?.let { it1 ->
                    binding.buttonGroup.setTextColor(
                        it1
                    )
                }
            }
            binding.buttonGroup.setBackgroundResource(R.drawable.unselected_button_back)
            binding.buttonChat.tag = "selected"
            binding.buttonGroup.tag = "unselected"
            binding.viewPager.currentItem = 0
        }