热门标签 | 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的使用方法。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
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社区 版权所有