Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
ViewPagerIndicator導(dǎo)航欄指示器運(yùn)行效果:

實(shí)現(xiàn)這個(gè)效果,我是看了很多大神寫的博客和視頻后自己敲的,歡迎指正
github地址:https://github.com/dl10210950/TabViewPagerIndicator
自定義一個(gè)ViewPagerIndicator
自定義一個(gè)Indicator繼承LinearLayout,在構(gòu)造方法里面設(shè)置畫筆的一些屬性
public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();//實(shí)例化畫筆
mPaint.setAntiAlias(true);//設(shè)置抗鋸齒
mPaint.setColor(Color.parseColor("#c9b2ab"));//設(shè)置畫筆的顏色,也就是三角形的顏色
mPaint.setStyle(Paint.Style.FILL);//設(shè)置style
mPaint.setPathEffect(new CornerPathEffect(3));//設(shè)置三角形圓角
}
重寫onSizeChanged方法來設(shè)置指示器三角形的
/**
* 當(dāng)控件的寬高發(fā)生變化時(shí)都會(huì)回調(diào)這個(gè)方法
* @param w 控件的長(zhǎng)度
* @param h 高度
* @param oldw 以前的長(zhǎng)度
* @param oldh 以前的高度
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
/*
控件的長(zhǎng)度(3個(gè)tab的總長(zhǎng)度)/3就得到每個(gè)tab的長(zhǎng)度
而三角形的寬度又是每個(gè)tab的長(zhǎng)度的六分之一
*/
mTriangleWidth = (int) (w / 3 * RADIO_TRIANGLE_WIDTH);
/*
三角形初始的偏移量,也就是三角形初始的位置
w / 3 / 2:每個(gè)tab長(zhǎng)度的一半就是tab的正中間
再減去三角形寬度的一半,這個(gè)偏移量剛好三角形就顯示在tab的正中間
*/
mInitTranslationX = w / 3 / 2 - mTriangleWidth / 2;
initTriangle();
}
/**
* 初始化三角形
*/
private void initTriangle() {
mTriangleHeight = mTriangleWidth / 2;//三角形的高度設(shè)置為寬度的一半
//實(shí)例化三角形
mPath = new Path();
mPath.moveTo(0, 0);//三角形的起點(diǎn)
mPath.lineTo(mTriangleWidth, 0);//首先繪制一條寬度為三角形寬度的一條直線
//然后繪制三角形右邊的那條線x坐標(biāo)為寬度的一半,y坐標(biāo)為寬度的一半
mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
mPath.close();//完成閉合,繪制了一個(gè)完整的三角形
}
重寫dispatchDraw來繪制指示器:
/**
* 繪制
* @param canvas
*/
@Override
protected void dispatchDraw(Canvas canvas) {
/*
canvas.save();和canvas.restore();是兩個(gè)相互匹配出現(xiàn)的,作用是用來保存畫布的狀態(tài)和取出保存的狀態(tài)的。
save:用來保存Canvas的狀態(tài)。save之后,可以調(diào)用Canvas的平移、放縮、旋轉(zhuǎn)、錯(cuò)切、裁剪等操作
*/
canvas.save();
canvas.translate(mInitTranslationX + mTranslationX, getHeight()+2);//繪制之前先平移到指定的位置
canvas.drawPath(mPath,mPaint);//平移到指定的位置后開始繪制,
/*
restore:用來恢復(fù)Canvas之前保存的狀態(tài)。防止save后對(duì)Canvas執(zhí)行的操作對(duì)后續(xù)的繪制有影響。
*/
canvas.restore();
super.dispatchDraw(canvas);
}
重寫scroll方法來設(shè)置滑動(dòng)時(shí)指示器的偏移量:
/**
* 指示器根據(jù)手指滾動(dòng)而滾動(dòng)
* @param position
*/
public void scroll(int position, float offset) {
int tabWidth = getWidth() / 3;
mTranslationX = (int)(tabWidth * offset + position * tabWidth);//三角形的偏移量
invalidate();
}
在布局文件中使用
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:duanlian="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.duanlian.tabviewpagerindicator.view.ViewPagerIndicator android:id="@+id/id_indicator" android:layout_width="match_parent" android:layout_height="45dp" android:background="#000000" android:orientation="horizontal" duanlian:visible_tab_count="4"> <TextView android:id="@+id/main_yiyan" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:onClick="meiZi" android:text="江一燕" android:textColor="#ffffff" android:textSize="16sp" /> <TextView android:id="@+id/main_liya" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:onClick="meiZi" android:text="佟麗婭" android:textColor="#ffffff" android:textSize="16sp" /> <TextView android:id="@+id/yuanyuan" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:onClick="meiZi" android:text="高圓圓" android:textColor="#ffffff" android:textSize="16sp" /> </com.duanlian.tabviewpagerindicator.view.ViewPagerIndicator> <android.support.v4.view.ViewPager android:id="@+id/id_viewpager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>
根據(jù)你需要的導(dǎo)航欄的標(biāo)題數(shù)量來設(shè)置ViewPagerIndicator中間的TextView的數(shù)量
創(chuàng)建Fragment
根據(jù)你的需要?jiǎng)?chuàng)建Fragment的數(shù)量,我這里創(chuàng)建了3個(gè)Framgent,布局文件就一個(gè)TextView和一個(gè)ImageView。
我貼出其中一個(gè)Frament的代碼,其他兩個(gè)基本都是一樣的:
package com.duanlian.tabviewpagerindicator.fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.duanlian.tabviewpagerindicator.R;
public class FragmentA extends Fragment {
@Override
public void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.a_fragment, null);
return view;
}
@Override
public void onActivityCreated( Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/jiangyiyan" android:scaleType="fitXY" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:gravity="center_horizontal" android:text="FregmentA" android:textColor="#e44316" android:textSize="36dp" /> </FrameLayout>
Activity中的邏輯
滑動(dòng)VIewPager讓導(dǎo)航欄的標(biāo)題改變得實(shí)現(xiàn):
//定義兩個(gè)顏色和大小
private int colorA = Color.parseColor("#ff00ff");//選中的顏色
private int colorB = Color.WHITE;//默認(rèn)的顏色
private float sizeA = 19f;//選中大小
private float sizeB = 16f;//默認(rèn)大小
/**
* 設(shè)置監(jiān)聽的方法
*/
private void setListener() {
//ViewPager的監(jiān)聽事件
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//讓indicator和ViewPager聯(lián)動(dòng)
mIndicator.scroll(position, positionOffset);
}
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
setTextAttribute(colorA,colorB,colorB,sizeA,sizeB,sizeB);
break;
case 1:
setTextAttribute(colorB,colorA,colorB,sizeB,sizeA,sizeB);
break;
case 2:
setTextAttribute(colorB,colorB,colorA,sizeB,sizeB,sizeA);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 自己定義一個(gè)給textView設(shè)置屬性的方法
*/
private void setTextAttribute(int color1, int color2, int color3, float size1, float size2, float size3){
yiYan.setTextColor(color1);
liYa.setTextColor(color2);
yuanYuan.setTextColor(color3);
yiYan.setTextSize(size1);
liYa.setTextSize(size2);
yuanYuan.setTextSize(size3);
}
點(diǎn)擊導(dǎo)航欄的標(biāo)題讓ViewPager聯(lián)動(dòng)的實(shí)現(xiàn):
/**
* 導(dǎo)航欄點(diǎn)擊事件
* @param view
*/
public void meiZi(View view){
switch (view.getId()) {
case R.id.main_yiyan:
mViewPager.setCurrentItem(0);
break;
case R.id.main_liya:
mViewPager.setCurrentItem(1);
break;
case R.id.yuanyuan:
mViewPager.setCurrentItem(2);
break;
}
}
整個(gè)Activity的代碼如下:
package com.duanlian.tabviewpagerindicator;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import com.duanlian.tabviewpagerindicator.adapter.MyFragmentPagerAdapter;
import com.duanlian.tabviewpagerindicator.fragment.FragmentA;
import com.duanlian.tabviewpagerindicator.fragment.FragmentB;
import com.duanlian.tabviewpagerindicator.fragment.FragmentC;
import com.duanlian.tabviewpagerindicator.view.ViewPagerIndicator;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends FragmentActivity {
private ViewPager mViewPager;
private ViewPagerIndicator mIndicator;//導(dǎo)航欄指示器
private List<Fragment> mContents;//裝載fragment的集合
private MyFragmentPagerAdapter mAdapter;
private TextView yiYan;
private TextView liYa;
private TextView yuanYuan;
//定義兩個(gè)顏色和大小
private int colorA = Color.parseColor("#ff00ff");//選中的顏色
private int colorB = Color.WHITE;//默認(rèn)的顏色
private float sizeA = 19f;//選中大小
private float sizeB = 16f;//默認(rèn)大小
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initViews();
setListener();
}
/**
* 初始化view
*/
private void initViews() {
mIndicator = (ViewPagerIndicator) findViewById(R.id.id_indicator);
mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
//3個(gè)標(biāo)題
yiYan = (TextView) findViewById(R.id.main_yiyan);
liYa = (TextView) findViewById(R.id.main_liya);
yuanYuan = (TextView) findViewById(R.id.yuanyuan);
FragmentA fragmentA = new FragmentA();
FragmentB fragmentB = new FragmentB();
FragmentC fragmentC = new FragmentC();
mContents = new ArrayList<>();
mContents.add(fragmentA);
mContents.add(fragmentB);
mContents.add(fragmentC);
mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), mContents);
mViewPager.setAdapter(mAdapter);
//設(shè)置默認(rèn)頁(yè)面和顏色
mViewPager.setCurrentItem(0);
setTextAttribute(colorA,colorB,colorB,sizeA,sizeB,sizeB);
}
/**
* 導(dǎo)航欄點(diǎn)擊事件
* @param view
*/
public void meiZi(View view){
switch (view.getId()) {
case R.id.main_yiyan:
mViewPager.setCurrentItem(0);
break;
case R.id.main_liya:
mViewPager.setCurrentItem(1);
break;
case R.id.yuanyuan:
mViewPager.setCurrentItem(2);
break;
}
}
/**
* 設(shè)置監(jiān)聽的方法
*/
private void setListener() {
//ViewPager的監(jiān)聽事件
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//讓indicator和ViewPager聯(lián)動(dòng)
mIndicator.scroll(position, positionOffset);
}
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
setTextAttribute(colorA,colorB,colorB,sizeA,sizeB,sizeB);
break;
case 1:
setTextAttribute(colorB,colorA,colorB,sizeB,sizeA,sizeB);
break;
case 2:
setTextAttribute(colorB,colorB,colorA,sizeB,sizeB,sizeA);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
/**
* 自己定義一個(gè)給textView設(shè)置屬性的方法
*/
private void setTextAttribute(int color1, int color2, int color3, float size1, float size2, float size3){
yiYan.setTextColor(color1);
liYa.setTextColor(color2);
yuanYuan.setTextColor(color3);
yiYan.setTextSize(size1);
liYa.setTextSize(size2);
yuanYuan.setTextSize(size3);
}
}
Adapter的編寫
package com.duanlian.tabviewpagerindicator.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import java.util.List;
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> list;
public MyFragmentPagerAdapter(FragmentManager fm,List<Fragment> mContents) {
super(fm);
this.list = mContents;
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
}
完成了,歡迎大神指正,虛心受教
demo下載地址:炫酷導(dǎo)航欄指示器
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android BottomNavigationView與Fragment重建與重疊問題解決方法探索
- Android關(guān)于BottomNavigationView使用指南
- Android BottomNavigationView底部導(dǎo)航效果
- Android中TabLayout+ViewPager 簡(jiǎn)單實(shí)現(xiàn)app底部Tab導(dǎo)航欄
- Android 利用ViewPager+GridView實(shí)現(xiàn)首頁(yè)導(dǎo)航欄布局分頁(yè)效果
- Android BottomNavigationView結(jié)合ViewPager實(shí)現(xiàn)底部導(dǎo)航欄步驟詳解
相關(guān)文章
Android 實(shí)現(xiàn)夜間模式的快速簡(jiǎn)單方法實(shí)例詳解
這篇文章主要介紹了Android 實(shí)現(xiàn)夜間模式的快速簡(jiǎn)單方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android超詳細(xì)講解組件AdapterView的使用
AdapterView組件是一組重要的組件,AdapterView本身是一個(gè)抽象基類,它派生的子類在用法上十分相似,從AdapterView派生出的三個(gè)子類:AdsListView、AdsSpinner、AdapterViewAnimator,這3個(gè)子類依然是抽象的,實(shí)際運(yùn)用時(shí)需要它們的子類2022-03-03
Android開發(fā)之AlertDialog實(shí)現(xiàn)彈出對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)之AlertDialog實(shí)現(xiàn)彈出對(duì)話框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
Android開發(fā)簡(jiǎn)單實(shí)現(xiàn)搖動(dòng)動(dòng)畫的方法
這篇文章主要介紹了Android開發(fā)簡(jiǎn)單實(shí)現(xiàn)搖動(dòng)動(dòng)畫的方法,結(jié)合實(shí)例形式分析了Android搖動(dòng)動(dòng)畫的布局與功能簡(jiǎn)單實(shí)現(xiàn)方法,需要的朋友可以參考下2017-10-10
react native打包apk文件安裝好之后進(jìn)入應(yīng)用閃退的解決方案
這篇文章主要介紹了react native打包apk文件安裝好之后進(jìn)入應(yīng)用閃退的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
Android 新聞界面模擬ListView和ViewPager的應(yīng)用
本文主要介紹 Android ListView和ViewPager的應(yīng)用,這里模擬了新聞界面及實(shí)現(xiàn)示例代碼,有需要的小伙伴可以參考下2016-09-09
Android實(shí)現(xiàn)微信右側(cè)頂部下拉對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)微信右側(cè)頂部下拉對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Android修行手冊(cè)之ConstraintLayout布局使用詳解
這篇文章主要為大家介紹了Android修行手冊(cè)之ConstraintLayout使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

