热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidUI组件SlidingTabLayout实现ViewPager页滑动效果

AndroidUI组件SlidingTabLayout实现ViewPager页滑动效果-使用SlidingTabLayout需要准备2个类,分别是SlidingTabLayout,

使用SlidingTabLayout需要准备2个类,分别是 SlidingTabLayout,与SlidingTabStrip,,放进项目中时只用修改下包名即可。

效果制作的不是很好。
这篇文章,也是在网上搜了很多资源参考,对 SlidingTabLayout.java和SlidingTabStrip.java进行了修改。大家可以更改他的格式字体大小、选中状态,分割线调整等等。先上传这两个文件,改动支出都做了注释。
SlidingTabLayout.java

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.my.slidingtablayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Build;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * To be used with ViewPager to provide a tab indicator component which give constant feedback as to
 * the user's scroll progress.
 * 

* To use the component, simply add it to your view hierarchy. Then in your * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for. *

* The colors can be customized in two ways. The first and simplest is to provide an array of colors * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The * alternative is via the {@link TabColorizer} interface which provides you complete control over * which color is used for any individual position. *

* The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, * providing the layout ID of your custom layout. */ public class SlidingTabLayout extends HorizontalScrollView { /** * Allows complete control over the colors drawn in the tab layout. Set with * {@link #setCustomTabColorizer(TabColorizer)}. */ public interface TabColorizer { /** * @return return the color of the indicator used when {@code position} is selected. */ int getIndicatorColor(int position); /** * @return return the color of the divider drawn to the right of {@code position}. */ int getDividerColor(int position); } private static final int TITLE_OFFSET_DIPS = 24; private static final int TAB_VIEW_PADDING_DIPS = 16; //内边距 private static int TAB_VIEW_TEXT_SIZE_SP = 16; //字体大小 private int mTitleOffset; private int mTabViewLayoutId; private int mTabViewTextViewId; // 定义两种需要添加的选项卡颜色 private int mDefaultTextColor; private int mSelectedTextColor; private ViewPager mViewPager; private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; private final SlidingTabStrip mTabStrip; public SlidingTabLayout(Context context) { this(context, null); } public SlidingTabLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获取选项卡颜色,如果未定义的话,则使用主题默认的颜色 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingTabLayout); int defaultTextColor = a.getColor( R.styleable.SlidingTabLayout_android_textColorPrimary, 0); mDefaultTextColor = a.getColor( R.styleable.SlidingTabLayout_textColorTabDefault, defaultTextColor); mSelectedTextColor = a.getColor( R.styleable.SlidingTabLayout_textColorTabSelected ,defaultTextColor); a.recycle(); // Disable the Scroll Bar setHorizontalScrollBarEnabled(false); // Make sure that the Tab Strips fills this View setFillViewport(true); mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density); mTabStrip = new SlidingTabStrip(context); addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } // 在每次选项改变时更新选项卡文本颜色的新方法 private void updateSelectedTitle(int position) { final PagerAdapter adapter = mViewPager.getAdapter(); for (int i = 0; i * If you only require simple custmisation then you can use * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve * similar effects. */ public void setCustomTabColorizer(TabColorizer tabColorizer) { mTabStrip.setCustomTabColorizer(tabColorizer); } /** * Sets the colors to be used for indicating the selected tab. These colors are treated as a * circular array. Providing one color will mean that all tabs are indicated with the same color. */ public void setSelectedIndicatorColors(int... colors) { mTabStrip.setSelectedIndicatorColors(colors); } /** * Sets the colors to be used for tab dividers. These colors are treated as a circular array. * Providing one color will mean that all tabs are indicated with the same color. */ public void setDividerColors(int... colors) { mTabStrip.setDividerColors(colors); } //...设置字体大小 public void setTitleSize(int size) { this.TAB_VIEW_TEXT_SIZE_SP = size; } /** * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so * that the layout can update it's scroll position correctly. * * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) */ public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { mViewPagerPageChangeListener = listener; } /** * Set the custom layout to be inflated for the tab views. * * @param layoutResId Layout id to be inflated * @param textViewId id of the {@link TextView} in the inflated view */ public void setCustomTabView(int layoutResId, int textViewId) { mTabViewLayoutId = layoutResId; mTabViewTextViewId = textViewId; } /** * Sets the associated view pager. Note that the assumption here is that the pager content * (number of tabs and tab titles) does not change after this call has been made. */ public void setViewPager(ViewPager viewPager) { mTabStrip.removeAllViews(); mViewPager = viewPager; if (viewPager != null) { viewPager.setOnPageChangeListener(new InternalViewPagerListener()); populateTabStrip(); } } /** * Create a default view to be used for tabs. This is called if a custom tab view is not set via * {@link #setCustomTabView(int, int)}. */ protected TextView createDefaultTabView(Context context) { TextView textView = new TextView(context); textView.setGravity(Gravity.CENTER); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); textView.setTypeface(Typeface.DEFAULT_BOLD); //...这会移除 Holo 的默认背景强调以及选项卡的粗体文本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // If we're running on Honeycomb or newer, then we can use the Theme's // selectableItemBackground to ensure that the View has a pressed state TypedValue outValue = new TypedValue(); getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true); textView.setBackgroundResource(outValue.resourceId); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style textView.setAllCaps(true); } int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density); textView.setPadding(padding, padding, padding, padding); return textView; } private void populateTabStrip() { final PagerAdapter adapter = mViewPager.getAdapter(); final OnClickListener tabClickListener = new TabClickListener(); for (int i = 0; i = tabStripChildCount) { return; } View selectedChild = mTabStrip.getChildAt(tabIndex); if (selectedChild != null) { // 调用在每次选项改变时更新文本颜色的新方案 updateSelectedTitle(tabIndex); int targetScrollX = selectedChild.getLeft() + positionOffset; if (tabIndex > 0 || positionOffset > 0) { // If we're not at the first child and are mid-scroll, make sure we obey the offset targetScrollX -= mTitleOffset; } scrollTo(targetScrollX, 0); } } private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { private int mScrollState; @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int tabStripChildCount = mTabStrip.getChildCount(); if ((tabStripChildCount == 0) || (position <0) || (position >= tabStripChildCount)) { return; } mTabStrip.onViewPagerPageChanged(position, positionOffset); View selectedTitle = mTabStrip.getChildAt(position); int extraOffset = (selectedTitle != null) ? (int) (positionOffset * selectedTitle.getWidth()) : 0; scrollToTab(position, extraOffset); if (mViewPagerPageChangeListener != null) { mViewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); } } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; if (mViewPagerPageChangeListener != null) { mViewPagerPageChangeListener.onPageScrollStateChanged(state); } } @Override public void onPageSelected(int position) { if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { mTabStrip.onViewPagerPageChanged(position, 0f); scrollToTab(position, 0); } if (mViewPagerPageChangeListener != null) { mViewPagerPageChangeListener.onPageSelected(position); } } } private class TabClickListener implements OnClickListener { @Override public void onClick(View v) { for (int i = 0; i

SlidingTabStrip.java

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.my.slidingtablayout;

import android.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;

class SlidingTabStrip extends LinearLayout {

 private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; //去除阴影
 private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
 private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 4;  //设置滚动条的高度
 private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;


 private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1;
 private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20;
 private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f;

 private final int mBottomBorderThickness;
 private final Paint mBottomBorderPaint;

 private final int mSelectedIndicatorThickness;
 private final Paint mSelectedIndicatorPaint;

 private final int mDefaultBottomBorderColor;

 private final Paint mDividerPaint;
 private final float mDividerHeight;

 private int mSelectedPosition;
 private float mSelectionOffset;

 private SlidingTabLayout.TabColorizer mCustomTabColorizer;
 private final SimpleTabColorizer mDefaultTabColorizer;

 SlidingTabStrip(Context context) {
  this(context, null);
 }

 SlidingTabStrip(Context context, AttributeSet attrs) {
  super(context, attrs);
  setWillNotDraw(false);

  final float density = getResources().getDisplayMetrics().density;

  TypedValue outValue = new TypedValue();
  context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);
  final int themeForegroundColor = outValue.data;

  mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
    DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);

  mDefaultTabColorizer = new SimpleTabColorizer();
  mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);
  mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor,
    DEFAULT_DIVIDER_COLOR_ALPHA));

  mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
  mBottomBorderPaint = new Paint();
  mBottomBorderPaint.setColor(mDefaultBottomBorderColor);

  mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
  mSelectedIndicatorPaint = new Paint();

  mDividerHeight = DEFAULT_DIVIDER_HEIGHT;
  mDividerPaint = new Paint();
  mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density));
 }

 void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
  mCustomTabColorizer = customTabColorizer;
  invalidate();
 }

 void setSelectedIndicatorColors(int... colors) {
  // Make sure that the custom colorizer is removed
  mCustomTabColorizer = null;
  mDefaultTabColorizer.setIndicatorColors(colors);
  invalidate();
 }

 void setDividerColors(int... colors) {
  // Make sure that the custom colorizer is removed
  mCustomTabColorizer = null;
  mDefaultTabColorizer.setDividerColors(colors);
  invalidate();
 }

 void onViewPagerPageChanged(int position, float positionOffset) {
  mSelectedPosition = position;
  mSelectiOnOffset= positionOffset;
  invalidate();
 }

 @Override
 protected void onDraw(Canvas canvas) {
  final int height = getHeight();
  final int childCount = getChildCount();
  final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height);
  final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
    ? mCustomTabColorizer
    : mDefaultTabColorizer;

  // Thick colored underline below the current selection
  if (childCount > 0) {
   View selectedTitle = getChildAt(mSelectedPosition);
   int left = selectedTitle.getLeft();
   int right = selectedTitle.getRight();
   int color = tabColorizer.getIndicatorColor(mSelectedPosition);

   if (mSelectionOffset > 0f && mSelectedPosition <(getChildCount() - 1)) {
    int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
    if (color != nextColor) {
     color = blendColors(nextColor, color, mSelectionOffset);
    }

    // Draw the selection partway between the tabs
    View nextTitle = getChildAt(mSelectedPosition + 1);
    left = (int) (mSelectionOffset * nextTitle.getLeft() +
      (1.0f - mSelectionOffset) * left);
    right = (int) (mSelectionOffset * nextTitle.getRight() +
      (1.0f - mSelectionOffset) * right);
   }

   mSelectedIndicatorPaint.setColor(color);

   canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
     height, mSelectedIndicatorPaint);
  }

  // Thin underline along the entire bottom edge
  canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);

  // Vertical separators between the titles
  int separatorTop = (height - dividerHeightPx) / 2;
  for (int i = 0; i 

上边因为使用了自定义的颜色,所以这里要在attrs.xml声明一下,不然找不到:



 
  
  
  
 

布局文件也要用到自定义:



 
 

 

最后一道就是在你的Activity运用这种开源:可以调整之处也做了说明

package com.example.my.slidingtablayout;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
 //创建 颜色数组 用来做viewpager的背景
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  ViewPager pager = (ViewPager) findViewById(R.id.view_pager);
  SlidingTabLayout tab = (SlidingTabLayout) findViewById(R.id.sliding);
  tab.setDividerColors(Color.TRANSPARENT); //设置标题的分割线
  tab.setSelectedIndicatorColors(Color.rgb(51, 181, 229)); //设置滚动条的颜色
  tab.setTitleSize(18); //...设置字体的颜色,默认16

  MyAdapte adapter = new MyAdapte();
  pager.setAdapter(adapter);
  tab.setViewPager(pager);
 }

 int[] colors = {0xFF123456, 0xFF654321, 0xFF336699};

 class MyAdapte extends PagerAdapter {
  //可以考虑把这个数组添加到集合里面
  String[] titles = {"AA", "BB", "CC"};


  ArrayList layouts = new ArrayList();

  MyAdapte() {

   for (int i = 0; i <3; i++) {
    LinearLayout l = new LinearLayout(MainActivity.this);
    l.setBackgroundColor(colors[i]);
    l.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    layouts.add(l);
   }

  }

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

  @Override
  public boolean isViewFromObject(View view, Object o) {
   return view == o;
  }

  @Override
  public Object instantiateItem(ViewGroup container, int position) {
   LinearLayout l = layouts.get(position);
   container.addView(l);
   return l;
  }

  @Override
  public void destroyItem(ViewGroup container, int position, Object object) {
   container.removeView(layouts.get(position));
  }

  @Override
  public CharSequence getPageTitle(int position) {
   //...可以返回集合list.get(position);
   return titles[position];
  }
 }
}

推荐阅读
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
author-avatar
手机用户2502852637_666
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有