问题:需要支持图片或颜色值的指示器
解决:如下效果
<com.core.ex.widget.IndicatorView
android:id="@+id/indicator_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
app:indicator_item_height="5dp"
app:indicator_item_space="10dp"
app:indicator_item_width="40dp"
app:selected_color="@color/cl_red"
app:unSelected_color="@color/cl_32a0fa" />
<com.core.ex.widget.IndicatorView
android:id="@+id/indicator_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="20dp"
app:indicator_item_height="30dp"
android:orientation="vertical"
app:indicator_item_space="10dp"
app:indicator_item_width="5dp"
app:selected_color="@color/cl_red"
app:unSelected_color="@color/cl_32a0fa" />
<com.core.ex.widget.IndicatorView
android:id="@+id/indicator_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="20dp"
android:orientation="horizontal"
app:indicator_item_height="40dp"
app:indicator_item_space="10dp"
app:indicator_item_width="40dp"
app:selected_image="@drawable/icon_main_home"
app:unSelected_image="@drawable/icon_main_list" />
package com.core.ex.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.core.ex.LogHelps;
import com.core.ex.R;
import com.core.ex.util.BitmapUtils;
/**
* @Author chentao 0000668668
* @Time 2023/5/8
* @Description 指示器显示
* 原点显示:宽高相等即可
* <p>------------------------------------------------------------------------------
* 圆形--底部水平居中显示:
* android:layout_gravity="bottom|center_horizontal"
* android:layout_marginBottom="20dp"
* app:indicator_item_height="5dp"
* app:indicator_item_space="5dp"
* app:indicator_item_width="5dp"
* app:selected_color="@color/cl_red"
* app:unSelected_color="@color/cl_32a0fa"
* android:orientation="horizontal"
* <p>------------------------------------------------------------------------------
* 圆角矩形底部水平居中显示:
* android:layout_gravity="bottom|center_horizontal"
* android:layout_marginBottom="20dp"
* app:indicator_item_height="5dp"
* app:indicator_item_space="10dp"
* app:indicator_item_width="40dp"
* app:selected_color="@color/cl_red"
* app:unSelected_color="@color/cl_32a0fa"
* android:orientation="horizontal"
* <p>------------------------------------------------------------------------------
* 圆形垂直右边居中显示:
* android:layout_gravity="right|center_vertical"
* android:layout_marginRight="20dp"
* app:indicator_item_height="5dp"
* app:indicator_item_space="5dp"
* app:indicator_item_width="5dp"
* app:selected_color="@color/cl_red"
* app:unSelected_color="@color/cl_32a0fa"
* android:orientation="vertical"
* <p>------------------------------------------------------------------------------
* 圆角矩形垂直右边居中显示:
* android:layout_gravity="right|center_vertical"
* android:layout_marginBottom="20dp"
* app:indicator_item_height="5dp"
* app:indicator_item_space="10dp"
* app:indicator_item_width="40dp"
* app:selected_color="@color/cl_red"
* app:unSelected_color="@color/cl_32a0fa"
* android:orientation="vertical"
* <p>--------------显示图片 同上----------------------------------------------------------------
* app:selected_color="@color/cl_red"
* app:unSelected_color="@color/cl_32a0fa"
* 替换为:
* app:selected_image="@drawable/icon_main_home"
* app:unSelected_image="@drawable/icon_main_list"
*/
public class IndicatorView extends View {
private Paint mPaint;
private int mOrientation = LinearLayout.HORIZONTAL;
private int currentIndex, totalIndex = 1;
private int centreX, startX;
private int mItemSpace = 10; // itme之间间距
private int mItemWidth = 40; // itme宽度
private int mItemHeight = 5; // itme高度
private int mItemSelectedColor, mItemUnselectedColor;
private Bitmap mItemSelectedBitmap, mItemUnselectedBitmap;
public IndicatorView(Context context) {
this(context, null);
}
public IndicatorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomViewAttr, defStyleAttr, 0);
mOrientation = typedArray.getInt(R.styleable.CustomViewAttr_android_orientation, mOrientation);
mItemHeight = (int) typedArray.getDimension(R.styleable.CustomViewAttr_indicator_item_height, mItemHeight);
mItemWidth = (int) typedArray.getDimension(R.styleable.CustomViewAttr_indicator_item_width, mItemWidth);
mItemSpace = (int) typedArray.getDimension(R.styleable.CustomViewAttr_indicator_item_space, mItemSpace);
BitmapDrawable drawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.CustomViewAttr_selected_image);
if (drawable != null) {
// 设置图片宽高为item宽高 避免图片过大显示不全
mItemSelectedBitmap = drawable.getBitmap();
mItemSelectedBitmap = BitmapUtils.alterBitmapSize(mItemSelectedBitmap, mItemHeight, mItemWidth);
}
drawable = (BitmapDrawable) typedArray.getDrawable(R.styleable.CustomViewAttr_unSelected_image);
if (drawable != null) {
// 设置图片宽高为item宽高 避免图片过大显示不全
mItemUnselectedBitmap = drawable.getBitmap();
mItemUnselectedBitmap = BitmapUtils.alterBitmapSize(mItemUnselectedBitmap, mItemHeight, mItemWidth);
}
LogHelps.i("mItemSelectedBitmap:" + mItemSelectedBitmap, "mItemUnselectedBitmap:" + mItemUnselectedBitmap);
mItemSelectedColor = typedArray.getColor(R.styleable.CustomViewAttr_selected_color, Color.LTGRAY);
mItemUnselectedColor = typedArray.getColor(R.styleable.CustomViewAttr_unSelected_color, Color.WHITE);
typedArray.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureHeight(int measureSpec) {
int result;
int desired = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (mOrientation) {
case LinearLayout.HORIZONTAL:
desired = mItemHeight + getPaddingBottom() + getPaddingTop();
break;
case LinearLayout.VERTICAL:
desired = (totalIndex - 1) * mItemSpace + (totalIndex) * mItemHeight + getPaddingBottom() + getPaddingTop();
break;
}
if (specMode == MeasureSpec.EXACTLY) {
result = Math.max(desired, specSize);
} else {
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(desired, specSize);
} else result = desired;
}
return result;
}
private int measureWidth(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int desired = 0;
switch (mOrientation) {
case LinearLayout.HORIZONTAL:
desired = (totalIndex - 1) * mItemSpace + (totalIndex) * mItemWidth + getPaddingLeft() + getPaddingRight();
break;
case LinearLayout.VERTICAL:
desired = mItemWidth + getPaddingLeft() + getPaddingRight();
break;
}
if (specMode == MeasureSpec.EXACTLY) {
result = Math.max(desired, specSize);
} else {
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(desired, specSize);
} else result = desired;
}
return result;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mOrientation) {
case LinearLayout.HORIZONTAL:
centreX = getWidth() / 2;
startX = centreX - ((totalIndex - 1) * mItemSpace + totalIndex * mItemWidth) / 2;
for (int i = 0; i < totalIndex; i++) {
if (mItemSelectedBitmap != null && mItemUnselectedBitmap != null) {
// 优先图片绘制
canvas.drawBitmap((i == currentIndex) ? mItemSelectedBitmap : mItemUnselectedBitmap, startX, 0, mPaint);
} else {
mPaint.setColor((i == currentIndex) ? mItemSelectedColor : mItemUnselectedColor);
canvas.drawRoundRect(new RectF(startX, 0, startX + mItemWidth, mItemHeight), mItemHeight, mItemHeight, mPaint);
}
startX += (mItemSpace + mItemWidth);
}
break;
case LinearLayout.VERTICAL:
centreX = getHeight() / 2;
startX = centreX - ((totalIndex - 1) * mItemSpace + totalIndex * mItemHeight) / 2;
for (int i = 0; i < totalIndex; i++) {
if (mItemSelectedBitmap != null && mItemUnselectedBitmap != null) {
// 优先图片绘制
canvas.drawBitmap((i == currentIndex) ? mItemSelectedBitmap : mItemUnselectedBitmap, 0, startX, mPaint);
} else {
mPaint.setColor((i == currentIndex) ? mItemSelectedColor : mItemUnselectedColor);
canvas.drawRoundRect(new RectF(0, startX, mItemWidth, startX + mItemHeight), mItemWidth, mItemWidth, mPaint);
}
startX += (mItemSpace + mItemHeight);
}
break;
}
}
public void setCurrentIndex(int currentIndex) {
if (this.currentIndex == currentIndex) {
return;
}
this.currentIndex = currentIndex;
requestLayout();
}
public int getCurrentIndex() {
return currentIndex;
}
public void setTotalIndex(int totalIndex) {
if (this.totalIndex == totalIndex) {
return;
}
int oldTotalIndex = this.totalIndex;
if (totalIndex < 1) return;
if (totalIndex < oldTotalIndex) {
if (currentIndex == totalIndex) currentIndex = totalIndex - 1;
}
this.totalIndex = totalIndex;
LogHelps.iLow("totalIndex=" + totalIndex);
post(() -> requestLayout());
}
public int getTotalIndex() {
return totalIndex;
}
}
<attr name="selected_image" format="reference" /> <!-- 选中的图片 -->
<attr name="unSelected_image" format="reference" /> <!-- 未选中的图片 -->
<attr name="selected_color" format="color" /> <!-- 字体等等选中的颜色 -->
<attr name="unSelected_color" format="color" /> <!-- 字体等等未选中的颜色 -->
<attr name="indicator_item_height" format="dimension" /> <!-- 指示器item高度 -->
<attr name="indicator_item_width" format="dimension" /> <!-- 指示器item宽度-->
<attr name="indicator_item_space" format="dimension" /> <!-- 指示器item之间的间距-->
<attr name="android:orientation" />