主界面 Activity

package com.test.viewpagerindicator;import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Window;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** viewpagerIndicator  标签指示器*/
public class MainActivity extends FragmentActivity {private ViewPager mViewPager;private ViewpagerIndicator mIndicator;private List<String> titles = Arrays.asList("天龙八部", "西游记", "红楼梦", "三国演义", "水浒传", "聊斋志异", "猛回头", "梦笔溪谈", "红与黑", "封神榜");private List<VpSimpleFragment> mFragments = new ArrayList<>();private FragmentPagerAdapter mAdapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {requestWindowFeature(Window.FEATURE_NO_TITLE); //去掉 titleBarsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);initView();initDatas();mIndicator.setVisibleTabCount(5);mIndicator.setTabItemTitles(titles);mViewPager.setAdapter(mAdapter);mIndicator.setViewPager(mViewPager, 0);}private void initView() {mViewPager = (ViewPager) findViewById(R.id.id_viewpager);mIndicator = (ViewpagerIndicator) findViewById(R.id.id_indictor);}private void initDatas() {for (String title : titles) {VpSimpleFragment fragment = VpSimpleFragment.newInstance(title);mFragments.add(fragment);}mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {@Overridepublic Fragment getItem(int position) {return mFragments.get(position);}@Overridepublic int getCount() {return mFragments.size();}};}}

自定义 组件 ViewpagerIndicator

package com.test.viewpagerindicator;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;import java.util.List;/*** 2. 绘制三角形**/
public class ViewpagerIndicator extends LinearLayout {private Paint mPaint; //画笔private Path mPath; //path类 可以定义3条线 绘制出三角形private int mTriangleWidth; //三角形的宽度private int mTriangleHeight; //三角形的高度//为了适应屏幕的大小 规定三角形为tab 的1/6private static final float RADIO_TRIANGLE_WIDTH = 1 / 6F;private int mInitTranslationX; //定义初始化的x轴的偏移量值 三角形的初始偏移位置,及第一次出现的X坐标private int mTranslationX; //移动时的距离private int mTabVisibleCount; // 屏幕可见tab的个数private static final int COUNT_DEFAULT_TAB = 4;//默认显示4个 tabprivate List<String> mTitles; //设置标签标题public ViewpagerIndicator(Context context) {this(context, null); //使用带一个参数的构造方法 去掉用 带2个参数的构造方法}public ViewpagerIndicator(Context context, AttributeSet attrs) {super(context, attrs);//在构造方法中获取自定义属性
//        获取可见tab的数量TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewpagerIndicator);mTabVisibleCount = a.getInt(R.styleable.ViewpagerIndicator_visible_tab_count, COUNT_DEFAULT_TAB);if (mTabVisibleCount < 0) {mTabVisibleCount = COUNT_DEFAULT_TAB;}a.recycle();//在构造方法中初始化画笔mPaint = new Paint();mPaint.setAntiAlias(true); //抗锯齿mPaint.setColor(Color.RED);/*  //另一种设置颜色的方式
//       mPaint.setColor(Color.parseColor("#ffffffff"));*/mPaint.setStyle(Paint.Style.FILL);//设置不让三角形的角度很尖锐mPaint.setPathEffect(new CornerPathEffect(3));}@Override//在该方法中设置一些子元素的 参数protected void onFinishInflate() {super.onFinishInflate();int cCount = getChildCount();if (cCount == 0) return;for (int i = 0; i < cCount; i++) {View view = getChildAt(i);//            LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();LinearLayout.LayoutParams lp = (LayoutParams) view.getLayoutParams();lp.weight = 0;lp.width = getScreenWidth() / mTabVisibleCount;view.setLayoutParams(lp);}setItemClickEvent();}/*** 获得屏幕的宽度** @return*/private int getScreenWidth() {WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics = new DisplayMetrics();wm.getDefaultDisplay().getMetrics(outMetrics);return outMetrics.widthPixels;}@Override  //在该方法中进行绘制三角形protected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);canvas.save();//平移到画笔开始位置canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 2); //加上2 表示让三角形往下移动//进行绘制canvas.drawPath(mPath, mPaint);canvas.restore();}@Override //当控件的宽高发生变化时 回调protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mTriangleWidth = (int) (w / mTabVisibleCount * RADIO_TRIANGLE_WIDTH); //三角形底边宽度mInitTranslationX = w / mTabVisibleCount / 2 - mTriangleWidth / 2; //三角形所在位置的 初始值x轴的偏移量initTriangle(); //初始化三角形}private void initTriangle() {mTriangleHeight = mTriangleWidth / 2; //三角形的高mPath = new Path();mPath.moveTo(0, 0);mPath.lineTo(mTriangleWidth, 0);mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);mPath.close();}/*** 指示器跟随手指进行滚动的计算** @param position* @param offset*/public void scroll(int position, float offset) {int tabWidth = getWidth() / mTabVisibleCount; //控件的宽度mTranslationX = (int) (tabWidth * offset + tabWidth * position); //三角形的偏移量//让盛装 tab的容器随着 指示器一起移动//为什么减2呢? 因为我们是从0 开始的if (position >= (mTabVisibleCount - 2) && offset > 0 && getChildCount() > mTabVisibleCount) {if (mTabVisibleCount != 1) {this.scrollTo((position - (mTabVisibleCount - 2)) * tabWidth + (int) (tabWidth * offset), 0);} else {this.scrollTo((int) (tabWidth * offset + tabWidth * position), 0);}}//三角形的位置发生改变之后进行重绘invalidate();}public void setTabItemTitles(List<String> titles) {if (titles != null && titles.size() > 0) {this.removeAllViews(); //清除布局文件中viewmTitles = titles;for (String title : mTitles) {addView(generateTextView(title));}setItemClickEvent();}}/*** 设置可见 tab 数量** @param count*/public void setVisibleTabCount(int count) {mTabVisibleCount = count;}/*** 根据title创建tab** @param title* @return*/private View generateTextView(String title) {TextView textView = new TextView(getContext());LinearLayout.LayoutParams lp = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);lp.width = getScreenWidth() / mTabVisibleCount;textView.setText(title);textView.setGravity(Gravity.CENTER);textView.setTextSize(18);textView.setTextColor(Color.BLUE);textView.setLayoutParams(lp);return textView;}/*** 在这里还存在一个问题,如果开发者需要在 mainactivity 中需要调用setOnPageChangeListener() 怎么办呢?* 所以我们在这里自己定义一个接口 ,方便使用者调用.*/public interface PageOnChangeListener {public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);public void onPageSelected(int position);public void onPageScrollStateChanged(int state);}public PageOnChangeListener mListener;public void setOnPageChangeListener(PageOnChangeListener listener) {this.mListener = listener;}private ViewPager mViewPager;/*** 终极大方法** @param viewPager* @param pos*/public void setViewPager(ViewPager viewPager, int pos) {this.mViewPager = viewPager;mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {//偏移量计算 tabWidth+positionOffset + position* tabWidthscroll(position, positionOffset);//自定义接口的回调if (mListener != null) {mListener.onPageScrolled(position, positionOffset, positionOffsetPixels);}}@Overridepublic void onPageSelected(int position) {//自定义接口的回调if (mListener != null) {mListener.onPageSelected(position);}highLightTextView(position); //高亮tab文本颜色}@Overridepublic void onPageScrollStateChanged(int state) {//自定义接口的回调if (mListener != null) {mListener.onPageScrollStateChanged(state);}}});mViewPager.setCurrentItem(pos);highLightTextView(pos); //高亮tab文本颜色}/*** 重置tab文本颜色*/public void resetTextViewColor(){for (int i = 0; i < getChildCount(); i++) {View view = getChildAt(i);if (view instanceof TextView){((TextView) view).setTextColor(Color.BLUE);}}}/*** 高亮显示某个选中的 tab* @param pos*/public void highLightTextView(int pos) {resetTextViewColor(); //高亮之前 调用View view = getChildAt(pos);if (view instanceof TextView){((TextView) view).setTextColor(Color.BLACK);}}/*** 设置 tab的点击事件*/public void setItemClickEvent(){for (int i = 0; i < getChildCount(); i++) {View view = getChildAt(i);final int finalI = i;view.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mViewPager.setCurrentItem(finalI);}});}}
}

创建的 Fragment

package com.test.viewpagerindicator;import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;/*** 1. 编写Fragment* A simple {@link Fragment} subclass.*/
public class VpSimpleFragment extends Fragment {private String mTitle;public static final String BUNDLE_TITLE = "title";//这里通过newInstance 传入参数public static VpSimpleFragment newInstance(String title) {Bundle bundle = new Bundle();bundle.putString(BUNDLE_TITLE, title);VpSimpleFragment fragment = new VpSimpleFragment();fragment.setArguments(bundle);return fragment;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {//在这个方法中把 标题的值取出来Bundle bundle = getArguments();if (bundle != null) {mTitle = bundle.getString(BUNDLE_TITLE);}//这里直接编写一个 TextView 作为 该fragment的内容进行显示 就不去编写布局文件lTextView textView = new TextView(getActivity());textView.setText(mTitle);textView.setGravity(Gravity.CENTER);textView.setTextColor(Color.RED);textView.setTextSize(24);return textView;}
}

布局文件 activity_main2.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:gaao="http://schemas.android.com/apk/res-atuo/com.test.viewpagerindicator"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--使用自定义导航的 指示器--><com.test.viewpagerindicator.ViewpagerIndicator
        android:id="@+id/id_indictor"android:layout_width="match_parent"android:layout_height="48dp"android:background="#888"gaao:visible_tab_count="4"android:orientation="horizontal"></com.test.viewpagerindicator.ViewpagerIndicator><android.support.v4.view.ViewPager
        android:id="@+id/id_viewpager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></android.support.v4.view.ViewPager>
</LinearLayout>

布局文件 activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:gaao="http://schemas.android.com/apk/res-atuo/com.test.viewpagerindicator"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><!--使用自定义导航的 指示器--><com.test.viewpagerindicator.ViewpagerIndicator
        android:id="@+id/id_indictor"android:layout_width="match_parent"android:layout_height="48dp"android:background="#888"gaao:visible_tab_count="4"android:orientation="horizontal"><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="短信11"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="收藏22"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="推荐33"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="短信44"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="收藏55"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="推荐66"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="短信77"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="收藏88"android:textColor="#ccffffff"android:textSize="18sp"/><TextView
            android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:text="推荐99"android:textColor="#ccffffff"android:textSize="18sp"/></com.test.viewpagerindicator.ViewpagerIndicator><android.support.v4.view.ViewPager
        android:id="@+id/id_viewpager"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></android.support.v4.view.ViewPager>
</LinearLayout>

自定义属性


<?xml version="1.0" encoding="utf-8"?>
<resources><!--这是一个自定义属性--><!--这是一个自定义属性--><!--这是一个自定义属性--><attr name="visible_tab_count" format="integer"/><declare-styleable name="ViewpagerIndicator"><attr name="visible_tab_count"/></declare-styleable><!--这是一个自定义属性--><!--这是一个自定义属性-->
</resources>

Android-自定义ViewPager指示器相关推荐

  1. android 自定义viewpager指示器,Android自定义View Flyme6的Viewpager指示器

    最新更新的Flyme6整体效果不错,动画效果增加了很多了,看了看flyme6的Viewpager指示器,觉得有点意思,就模仿写了一下,整体效果如下: Gradle allprojects { repo ...

  2. Android自定义ViewPager图片指示器,兼容实现底部横线指示器

    前言  记得以前自己使用过的ViewPager Indicator有JakeWharton大神的开源库ViewPagerIndicator,v4包自带的PagerTitleStrip以及Android ...

  3. 【指示器】自定义ViewPager指示器,和你见过的不太一样。

    这次要说的指示器可能和大家常见的不同,这个是纯绘制出来的,即只 onDraw出来的.也许不够完善,欢迎大家提出问题. github:https://github.com/ai2101039/YLPag ...

  4. Android 自定义ViewPager设置屏蔽左右滑动事件

    只要有欲望,就应该有奋斗的心.... 屏蔽左右滑动事件的viewPager public class CustomNoScrollViewPager extends ViewPager{private ...

  5. Android瀑布流仿京东,(二) 仿京东顶部伸缩渐变丶自定义viewpager指示器丶viewpager3D回廊丶recyclerview瀑布流...

    效果图如下: demo2.gif Demo2 1.仿京东首页顶部轮播图+搜索栏渐变 public class GradientScrollView extends ScrollView { publi ...

  6. android如何自定义viewpager,Android自定义ViewPager实现个性化的图片切换效果

    第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开始让ViewPager来做.时间长了,ViewPager的 ...

  7. Android 自定义viewpager 三张图片在同一屏幕轮播的效果

    github:https://github.com/nickeyCode/RoundImageViewPager 说实话不知道怎么描述这个效果,在网页上见得跟多,公司要求做这个效果得时候不知道怎么用文 ...

  8. Android自定义步骤指示器

    一,前言 本人编写博客是为了记录自己的成长过程,把自己的每一个知识点都记录下来,避免在新知识的冲击下印象衰退 二,背景 前些天公司有一个用户引导的需求,上方有个步骤指示器,虽然用简单的view+背景色 ...

  9. Android 自定义 HorizontalScrollView 横向滑动效果

    自从Gallery被谷歌废弃以后,Google推荐使用ViewPager和HorizontalScrollView来实现Gallery的效果.的确HorizontalScrollView可以实现Gal ...

  10. Android自定义view之ViewPager指示器——2

    Android自定义view之ViewPager指示器--2 上一篇<Android自定义view之ViewPager指示器--1>中我们一起写了测量和布局的流程.本篇我们继续讲解事件分发 ...

最新文章

  1. 谷歌大脑新研究:强化学习如何学会用声音来观察?
  2. C 中的static关键字
  3. boost解析xml文件
  4. leetcode55. 跳跃游戏
  5. 课时85.层叠性(掌握)
  6. python实现多智能体一致性_促进产学研,多智能体协同控制——科研与实践教学齐飞...
  7. php接收post参数乱码,学习猿地-php接收post参数乱码怎么办
  8. 架构设计 | 分布式系统调度,Zookeeper集群化管理
  9. Tomcat本地正常!但是部署到服务器后,mysql插入中文乱码问题解决!
  10. java 正则表达式 img_正则表达式处理图片地址、img标签的方法
  11. oracle 32 下载,oracle 11g 32位下载
  12. python没有main函数的概念吗_为什么Python没有main函数?
  13. html树形结构_数据结构-线性表.md
  14. mongo(删除操作)
  15. HDU - 2087 剪花布条(kmp)
  16. 灵活多变的keytool和openssl生成证书,应用tomcat和nginx
  17. Fortran入门教程(六)——循环结构
  18. 结构梁配筋最牛插件_吃货的牛排种类大盘点,你最爱的是几分熟?
  19. 美团java笔试题_美团笔试题目(Java后端5题2小时)
  20. Python接口自动化测试

热门文章

  1. 08 款Polo,1.4M BMG 发动机 配件号
  2. 笑话:​计算机系的男同学追班里一女同学,结果此女总是躲躲闪闪。男的看没戏,就另找了一个去追,结果这女的不满意了...
  3. CNN Features off-the-shelf: an Astounding Baseline for Recognition 论文笔记
  4. 电脑缩小文件夹后一致闪屏幕,直到卡死
  5. [9]-Administration-Tuning Presto Properties Reference
  6. 【计算机网络】数据链路层-湖南科技大学《计算机网络微课堂》笔记3.2
  7. C++学习笔记:const和mutable的多种用法【Cherno】
  8. 论品质自驾游正确打开方式:晒晒彭于晏的自驾游新装备
  9. 2019.7笔记本推荐指南by tyut程序爱好者协会 编辑@笔吧夏蒙乾
  10. jquery 删除全部子节点