Android 页面指示器

时间:2022-07-28 10:30:07

指未器类:

package com.youche.cango.activity.pubwidgt.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;

import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.youche.cango.R;
import com.youche.cango.utils.MobileInfoUtils;

import java.util.List;

/**
* Created by cango on 2017/2/3.
*/

public class TopHeadIndicator extends LinearLayout {

private Context context;

/**
* 绘制三角形的画笔
*/
private Paint mPaint;

private int mPaintWidth = 0;

private int mBottomPaintWidth = 0;
/**
* path构成一个三角形
*/
private Path mPath;

/**
* 三角形画笔颜色
*/
private int mTriangleColor = 0;

/**
* 三角形的宽度
*/
private int mTriangleWidth;

/**
* 三角形的高度
*/
private int mTriangleHeight;


/**
* 三角形的宽度为单个Tab的1/6
*/
private static final float RADIO_TRIANGEL = 1.0f / 6;

/**
* 三角形的最大宽度
*/
private final int DIMENSION_TRIANGEL_WIDTH = (int) (getScreenWidth() / 3 * RADIO_TRIANGEL);


/**
* 初始时,三角形指示器的偏移量
*/
private int mInitTranslationX;

/**
* 手指滑动时的偏移量
*/
private float mTranslationX;

/**
* 默认的Tab数量
*/
private static final int COUNT_DEFAULT_TAB = 4;
/**
* tab数量
*/
private int mTabVisibleCount = COUNT_DEFAULT_TAB;


/**
* tab上的内容
*/
private List<String> mTabTitles;

/**
* Item切换接口
*/
public interface IOnItemChangeListener{
void OnChange(int pos);
};

private IOnItemChangeListener iOnItemChangeListener;

public void setiOnItemChangeListener(IOnItemChangeListener iOnItemChangeListener) {
this.iOnItemChangeListener = iOnItemChangeListener;
}


/**
* 标题正常时的颜色
*/
private static int COLOR_TEXT_NORMAL = 0x77FFFFFF;
/**
* 标题选中时的颜色
*/
private static int COLOR_TEXT_HIGHLIGHTCOLOR = 0xFFFFFFFF;


public TopHeadIndicator(Context context) {
this(context, null);
this.context = context;
mPaintWidth = MobileInfoUtils.dp2px(1);
mBottomPaintWidth = MobileInfoUtils.dp2px(2.0f);
}


public TopHeadIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintWidth = MobileInfoUtils.dp2px(1);
mBottomPaintWidth = MobileInfoUtils.dp2px(2.0f);
initAttrs(context,attrs);
this.context = context;

}

public TopHeadIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaintWidth = MobileInfoUtils.dp2px(1);
mBottomPaintWidth = MobileInfoUtils.dp2px(2.0f);
initAttrs(context, attrs);

this.context = context;
}

/**
* 初始化属性
*/
private void initAttrs(Context context, AttributeSet attrs) {

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator, 0, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {

case R.styleable.ViewPagerIndicator_item_count:
mTabVisibleCount = a.getInt(R.styleable.ViewPagerIndicator_item_count, COUNT_DEFAULT_TAB); //指示条数
break;

case R.styleable.ViewPagerIndicator_titleNormalColor:
COLOR_TEXT_NORMAL = a.getColor(attr, Color.BLACK); //标题文本正常时的颜色
break;

case R.styleable.ViewPagerIndicator_titleSelectColor:
COLOR_TEXT_HIGHLIGHTCOLOR = a.getColor(attr, Color.BLACK); //标题文本选中时的颜色
break;

case R.styleable.ViewPagerIndicator_triangleColor:
mTriangleColor = a.getColor(attr, Color.BLACK); //标题文本选中时的颜色
break;

}

}

a.recycle();

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mTriangleColor);
mPaint.setStrokeWidth(mPaintWidth);

}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);


canvas.save();
canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1); // 画笔平移到正确的位置


mPaint.setColor(mTriangleColor);
mPaint.setStrokeWidth(mBottomPaintWidth);
canvas.drawLine(-getScreenWidth(),0,getScreenWidth(), 0,mPaint);

//mPaint.setColor(mTriangleColor);
mPaint.setStrokeWidth(mBottomPaintWidth * 0.5f);
canvas.drawLine(0,0,mTriangleWidth / 2, - mTriangleHeight,mPaint);
canvas.drawLine(mTriangleWidth / 2, - mTriangleHeight,mTriangleWidth,0,mPaint);

mPaint.setColor(Color.WHITE);
mPaint.setStrokeWidth(mBottomPaintWidth);
canvas.drawLine(mTriangleWidth,0,0,0,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_TRIANGEL);// 1/6 of
mTriangleWidth = Math.min(DIMENSION_TRIANGEL_WIDTH, mTriangleWidth);
mInitTranslationX = getWidth() / mTabVisibleCount / 2 - mTriangleWidth / 2;
initTriangle();
}

/**
* 初始化三角形指示器
*/
private void initTriangle() {
mPath = new Path();
mTriangleHeight = (int) (mTriangleWidth / 2 / Math.sqrt(2));

mPath.lineTo(mTriangleWidth / 2, - mTriangleHeight);
mPath.lineTo(mTriangleWidth, 0);

mPath.close();
}


/**
* 设置可见的tab的数量
*
* @param count
*/
public void setVisibleTabCount(int count) {
this.mTabVisibleCount = count;
}


/**
* 设置tab的标题内容 可选,可以自己在布局文件中写死
*
* @param datas
*/
public void setTabItemTitles(List<String> datas) {

if (datas != null && datas.size() > 0) {
this.removeAllViews(); // 如果传入的list有值,则移除布局文件中设置的view
this.mTabTitles = datas;
for (String title : mTabTitles) {
addView(generateTextView(title));
}
setItemClickEvent();
}

highLightTextView(0);
}

/**
* 高亮文本
*
* @param position
*/
protected void highLightTextView(int position) {
View view = getChildAt(position);
if (view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_HIGHLIGHTCOLOR);
}


}


/**
* 重置文本颜色
*/
private void resetTextViewColor() {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view instanceof TextView) {
((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
}
}
}


/**
* 设置点击事件
*/
public void setItemClickEvent() {
int cCount = getChildCount();
for (int i = 0; i < cCount; i++) {
final int j = i;
View view = getChildAt(i);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
resetTextViewColor();
highLightTextView(j);
scroll(j, 0);
if(iOnItemChangeListener != null){
iOnItemChangeListener.OnChange(j);
}
}
});
}
}


/**
* 根据标题生成我们的TextView
*
* @param text
* @return
*/
private TextView generateTextView(String text) {
TextView tv = new TextView(getContext());
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.width = getScreenWidth() / mTabVisibleCount;
tv.setGravity(Gravity.CENTER);
tv.setTextColor(COLOR_TEXT_NORMAL);
tv.setText(text);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
tv.setLayoutParams(lp);
return tv;
}




/**
* 指示器跟随手指滚动,以及容器滚动
*
* @param position
* @param offset
*/
public void scroll(int position, float offset) {
mTranslationX = getWidth() / mTabVisibleCount * (position + offset);
invalidate();
}


/**
* 设置布局中view的一些必要属性;如果设置了setTabTitles,布局中view则无效
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
int cCount = getChildCount();
if (cCount == 0)
return;

for (int i = 0; i < cCount; i++) {
View view = getChildAt(i);
LayoutParams lp = (LayoutParams) view.getLayoutParams();
lp.weight = 0;
lp.width = getScreenWidth() / mTabVisibleCount;
view.setLayoutParams(lp);
}

setItemClickEvent();
}




/**
* 获得屏幕的宽度
*
* @return
*/
public int getScreenWidth() {
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}

}


二.属性文件

<?xml version="1.0" encoding="utf-8"?>
<resources>

<!--签字ImgeView属性-->
<attr name="Text" format="string" />
<attr name="TextColor" format="color" />
<attr name="bgColor" format="color" />
<attr name="TextSize" format="dimension" />

<declare-styleable name="CustomTitleView">
<attr name="Text" />
<attr name="TextColor" />
<attr name="TextSize" />
<attr name="bgColor" />
</declare-styleable>


<!--登录页面的滑动指示器属性-->
<attr name="item_count" format="integer"></attr>
<attr name="titleNormalColor" format="color"></attr>
<attr name="titleSelectColor" format="color"></attr>
<attr name="triangleColor" format="color"></attr>

<declare-styleable name="ViewPagerIndicator">

<attr name="item_count" />
<attr name="titleNormalColor" />
<attr name="titleSelectColor" />
<attr name="triangleColor" />

</declare-styleable>

</resources>


三.在布局文件中使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:lxb="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white">

<include layout="@layout/rightoption_title"/>

<include layout="@layout/base_line" />

<com.youche.cango.activity.pubwidgt.view.TopHeadIndicator
android:id="@+id/linear_indicator"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/white"
android:orientation="horizontal"
lxb:item_count="2"
lxb:titleNormalColor="@color/color_504E67"
lxb:titleSelectColor="@color/CG_Oange_line"
lxb:triangleColor="@color/CG_base_line">

</com.youche.cango.activity.pubwidgt.view.TopHeadIndicator>

<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.youche.cango.activity.pubwidgt.view.RecycView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.youche.cango.activity.pubwidgt.view.RecycView>

</android.support.v4.widget.SwipeRefreshLayout>

</LinearLayout>