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

實現(xiàn)這個效果,我是看了很多大神寫的博客和視頻后自己敲的,歡迎指正
github地址:https://github.com/dl10210950/TabViewPagerIndicator
自定義一個ViewPagerIndicator
自定義一個Indicator繼承LinearLayout,在構造方法里面設置畫筆的一些屬性
public ViewPagerIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();//實例化畫筆
mPaint.setAntiAlias(true);//設置抗鋸齒
mPaint.setColor(Color.parseColor("#c9b2ab"));//設置畫筆的顏色,也就是三角形的顏色
mPaint.setStyle(Paint.Style.FILL);//設置style
mPaint.setPathEffect(new CornerPathEffect(3));//設置三角形圓角
}
重寫onSizeChanged方法來設置指示器三角形的
/**
* 當控件的寬高發(fā)生變化時都會回調這個方法
* @param w 控件的長度
* @param h 高度
* @param oldw 以前的長度
* @param oldh 以前的高度
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
/*
控件的長度(3個tab的總長度)/3就得到每個tab的長度
而三角形的寬度又是每個tab的長度的六分之一
*/
mTriangleWidth = (int) (w / 3 * RADIO_TRIANGLE_WIDTH);
/*
三角形初始的偏移量,也就是三角形初始的位置
w / 3 / 2:每個tab長度的一半就是tab的正中間
再減去三角形寬度的一半,這個偏移量剛好三角形就顯示在tab的正中間
*/
mInitTranslationX = w / 3 / 2 - mTriangleWidth / 2;
initTriangle();
}
/**
* 初始化三角形
*/
private void initTriangle() {
mTriangleHeight = mTriangleWidth / 2;//三角形的高度設置為寬度的一半
//實例化三角形
mPath = new Path();
mPath.moveTo(0, 0);//三角形的起點
mPath.lineTo(mTriangleWidth, 0);//首先繪制一條寬度為三角形寬度的一條直線
//然后繪制三角形右邊的那條線x坐標為寬度的一半,y坐標為寬度的一半
mPath.lineTo(mTriangleWidth / 2, -mTriangleHeight);
mPath.close();//完成閉合,繪制了一個完整的三角形
}
重寫dispatchDraw來繪制指示器:
/**
* 繪制
* @param canvas
*/
@Override
protected void dispatchDraw(Canvas canvas) {
/*
canvas.save();和canvas.restore();是兩個相互匹配出現(xiàn)的,作用是用來保存畫布的狀態(tài)和取出保存的狀態(tài)的。
save:用來保存Canvas的狀態(tài)。save之后,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作
*/
canvas.save();
canvas.translate(mInitTranslationX + mTranslationX, getHeight()+2);//繪制之前先平移到指定的位置
canvas.drawPath(mPath,mPaint);//平移到指定的位置后開始繪制,
/*
restore:用來恢復Canvas之前保存的狀態(tài)。防止save后對Canvas執(zhí)行的操作對后續(xù)的繪制有影響。
*/
canvas.restore();
super.dispatchDraw(canvas);
}
重寫scroll方法來設置滑動時指示器的偏移量:
/**
* 指示器根據(jù)手指滾動而滾動
* @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ù)你需要的導航欄的標題數(shù)量來設置ViewPagerIndicator中間的TextView的數(shù)量
創(chuàng)建Fragment
根據(jù)你的需要創(chuàng)建Fragment的數(shù)量,我這里創(chuàng)建了3個Framgent,布局文件就一個TextView和一個ImageView。
我貼出其中一個Frament的代碼,其他兩個基本都是一樣的:
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中的邏輯
滑動VIewPager讓導航欄的標題改變得實現(xiàn):
//定義兩個顏色和大小
private int colorA = Color.parseColor("#ff00ff");//選中的顏色
private int colorB = Color.WHITE;//默認的顏色
private float sizeA = 19f;//選中大小
private float sizeB = 16f;//默認大小
/**
* 設置監(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)動
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) {
}
});
}
/**
* 自己定義一個給textView設置屬性的方法
*/
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);
}
點擊導航欄的標題讓ViewPager聯(lián)動的實現(xià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;
}
}
整個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;//導航欄指示器
private List<Fragment> mContents;//裝載fragment的集合
private MyFragmentPagerAdapter mAdapter;
private TextView yiYan;
private TextView liYa;
private TextView yuanYuan;
//定義兩個顏色和大小
private int colorA = Color.parseColor("#ff00ff");//選中的顏色
private int colorB = Color.WHITE;//默認的顏色
private float sizeA = 19f;//選中大小
private float sizeB = 16f;//默認大小
@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個標題
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);
//設置默認頁面和顏色
mViewPager.setCurrentItem(0);
setTextAttribute(colorA,colorB,colorB,sizeA,sizeB,sizeB);
}
/**
* 導航欄點擊事件
* @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;
}
}
/**
* 設置監(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)動
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) {
}
});
}
/**
* 自己定義一個給textView設置屬性的方法
*/
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下載地址:炫酷導航欄指示器
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Android 實現(xiàn)夜間模式的快速簡單方法實例詳解
這篇文章主要介紹了Android 實現(xiàn)夜間模式的快速簡單方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-09-09
Android開發(fā)之AlertDialog實現(xiàn)彈出對話框
這篇文章主要為大家詳細介紹了Android開發(fā)之AlertDialog實現(xiàn)彈出對話框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09
Android開發(fā)簡單實現(xiàn)搖動動畫的方法
這篇文章主要介紹了Android開發(fā)簡單實現(xiàn)搖動動畫的方法,結合實例形式分析了Android搖動動畫的布局與功能簡單實現(xiàn)方法,需要的朋友可以參考下2017-10-10
react native打包apk文件安裝好之后進入應用閃退的解決方案
這篇文章主要介紹了react native打包apk文件安裝好之后進入應用閃退的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
Android 新聞界面模擬ListView和ViewPager的應用
本文主要介紹 Android ListView和ViewPager的應用,這里模擬了新聞界面及實現(xiàn)示例代碼,有需要的小伙伴可以參考下2016-09-09
Android修行手冊之ConstraintLayout布局使用詳解
這篇文章主要為大家介紹了Android修行手冊之ConstraintLayout使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09

