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

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

这篇文章主要介绍了AndroidUI组件SlidingTabLayout实现ViewPager页滑动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

使用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) &#63; (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
    &#63; 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声明一下,不然找不到:

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
  
  
  
 

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

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 

 


最后一道就是在你的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];
  }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
author-avatar
劲朋_511
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有