version:1.9
fix: update:修改包名,添加推送
This commit is contained in:
70
app/src/main/java/com/uiui/aios/view/CustomContent.java
Normal file
70
app/src/main/java/com/uiui/aios/view/CustomContent.java
Normal file
@@ -0,0 +1,70 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
public class CustomContent extends FrameLayout implements CustomContentCallbacks {
|
||||
|
||||
public CustomContent(@NonNull Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public CustomContent(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public CustomContent(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShow(boolean fromResume) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHide() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollProgressChanged(float progress) {
|
||||
|
||||
}
|
||||
|
||||
// 滑到负一屏是否再允许滑动,true:允许滑动到主屏,false:不允许再滑动
|
||||
@Override
|
||||
public boolean isScrollingAllowed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
|
||||
// add by codemx.cn ---- 20190712 ---plus- start
|
||||
// modify by codemx.cn ---- 20190712 ---plus- start
|
||||
public interface CustomContentCallbacks {
|
||||
|
||||
// Custom content is completely shown. {@code fromResume} indicates whether this was caused
|
||||
// by a onResume or by scrolling otherwise.
|
||||
void onShow(boolean fromResume);
|
||||
|
||||
// Custom content is completely hidden
|
||||
void onHide();
|
||||
|
||||
// Custom content scroll progress changed. From 0 (not showing) to 1 (fully showing).
|
||||
void onScrollProgressChanged(float progress);
|
||||
|
||||
// Indicates whether the user is allowed to scroll away from the custom content.
|
||||
boolean isScrollingAllowed();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* 定义水平方向的距离
|
||||
*/
|
||||
public class HorizontalItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private int space;//定义2个Item之间的距离
|
||||
|
||||
public HorizontalItemDecoration(int space, Context mContext) {
|
||||
this.space = dip2px(space, mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
int totalCount = parent.getAdapter().getItemCount();
|
||||
if (position == 0) {//第一个
|
||||
outRect.left = space;
|
||||
outRect.right = space / 2;
|
||||
} else if (position == totalCount - 1) {//最后一个
|
||||
outRect.left = space / 2;
|
||||
outRect.right = space;
|
||||
} else {//中间其它的
|
||||
outRect.left = space / 2;
|
||||
outRect.right = space / 2;
|
||||
}
|
||||
}
|
||||
|
||||
public int dip2px(float dpValue, Context context) {
|
||||
final float scale = context.getResources().getDisplayMetrics().density;
|
||||
return (int) (dpValue * scale + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
82
app/src/main/java/com/uiui/aios/view/JzvdStdAssert.java
Normal file
82
app/src/main/java/com/uiui/aios/view/JzvdStdAssert.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import cn.jzvd.JzvdStd;
|
||||
|
||||
|
||||
public class JzvdStdAssert extends JzvdStd {
|
||||
private onVideoCompletionListener onVideoCompletionListener;
|
||||
private ScreenOrientationChangeListener changeListener;
|
||||
private GotoFullScreenListener gotoFullScreenListener;
|
||||
|
||||
public JzvdStdAssert(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public JzvdStdAssert(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPrepared() {
|
||||
Log.e("onStateChanged", "onPrepared");
|
||||
state = STATE_PREPARED;
|
||||
if (!preloading) {
|
||||
mediaInterface.start();
|
||||
preloading = false;
|
||||
}
|
||||
onStatePlaying();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCompletion() {
|
||||
super.onCompletion();
|
||||
onVideoCompletionListener.onVideoComplet();
|
||||
Log.e("onStateChanged", "onCompletion");
|
||||
}
|
||||
|
||||
public void setOnCompletionListener(onVideoCompletionListener listener) {
|
||||
this.onVideoCompletionListener = listener;
|
||||
}
|
||||
|
||||
public void setScreenOrientationChangeListener(ScreenOrientationChangeListener listener) {
|
||||
this.changeListener = listener;
|
||||
}
|
||||
|
||||
public void setGotoFullScreenListener(GotoFullScreenListener listener) {
|
||||
this.gotoFullScreenListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoNormalScreen() {
|
||||
super.gotoNormalScreen();
|
||||
changeListener.onOrientationChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotoFullscreen() {
|
||||
super.gotoFullscreen();
|
||||
gotoFullScreenListener.onGotoFullScreen();
|
||||
}
|
||||
|
||||
//视频播放完成回调
|
||||
public interface onVideoCompletionListener {
|
||||
void onVideoComplet();
|
||||
}
|
||||
|
||||
//退出全屏回调
|
||||
public interface ScreenOrientationChangeListener {
|
||||
void onOrientationChange();
|
||||
}
|
||||
|
||||
//进入全屏回调
|
||||
public interface GotoFullScreenListener {
|
||||
void onGotoFullScreen();
|
||||
}
|
||||
|
||||
}
|
||||
180
app/src/main/java/com/uiui/aios/view/MyGridLayout.java
Normal file
180
app/src/main/java/com/uiui/aios/view/MyGridLayout.java
Normal file
@@ -0,0 +1,180 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
|
||||
import com.uiui.aios.R;
|
||||
import com.uiui.aios.bean.DesktopIcon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
/**
|
||||
* 自定义布局组件
|
||||
*
|
||||
* @author zihao
|
||||
*/
|
||||
public class MyGridLayout extends ViewGroup {
|
||||
int margin = 2;// 每个格子的水平和垂直间隔
|
||||
int colums = 4;//列数
|
||||
int rows = 3;//行数
|
||||
int count = 0;
|
||||
|
||||
private GridAdatper adapter;
|
||||
private String TAG = MyGridLayout.class.getSimpleName();
|
||||
|
||||
@SuppressLint("Recycle")
|
||||
public MyGridLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
if (attrs != null) {
|
||||
TypedArray a = getContext().obtainStyledAttributes(attrs,
|
||||
R.styleable.MyGridLayout);
|
||||
margin = a.getInteger(R.styleable.MyGridLayout_itemMargin, 2);
|
||||
colums = a.getInteger(R.styleable.MyGridLayout_numColumns, 4);
|
||||
rows = a.getInteger(R.styleable.MyGridLayout_numRows, 3);
|
||||
}
|
||||
}
|
||||
|
||||
public MyGridLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public MyGridLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public void setColums(int c) {
|
||||
this.colums = c;
|
||||
}
|
||||
|
||||
public void setRows(int r) {
|
||||
this.rows = r;
|
||||
}
|
||||
|
||||
public void set(int c, int r) {
|
||||
this.colums = c;
|
||||
this.rows = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
count = getChildCount();
|
||||
if (count == 0) {
|
||||
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
|
||||
}
|
||||
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int height = b - t;// 布局区域高度
|
||||
int width = r - l;// 布局区域宽度
|
||||
// int rows = count % colums == 0 ? count / colums : count / colums + 1;// 行数
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
int gridW = (width - margin * (colums + 1)) / colums;// 格子宽度
|
||||
int gridH = (height - margin * (rows + 1)) / rows;// 格子高度
|
||||
|
||||
int left;
|
||||
int top = margin + margin / 2;
|
||||
|
||||
for (int i = 0; i < rows; i++) {// 遍历行
|
||||
for (int j = 0; j < colums; j++) {// 遍历每一行的元素
|
||||
View child = this.getChildAt(i * colums + j);
|
||||
if (child == null) {
|
||||
return;
|
||||
}
|
||||
// if (j == 0) {
|
||||
left = j * gridW + (j + 1) * margin + margin / 2;
|
||||
// } else {
|
||||
// left = j * gridW + (j + 1) * margin;
|
||||
// }
|
||||
// 如果当前布局宽度和测量宽度不一样,就直接用当前布局的宽度重新测量
|
||||
if (gridW != child.getMeasuredWidth()
|
||||
|| gridH != child.getMeasuredHeight()) {
|
||||
child.measure(makeMeasureSpec(gridW, EXACTLY),
|
||||
makeMeasureSpec(gridH, EXACTLY));
|
||||
}
|
||||
child.layout(left, top, left + gridW, top + gridH);
|
||||
// Log.e(TAG, "onLayout: left = " + left);
|
||||
// Log.e(TAG, "onLayout: top = " + top);
|
||||
// Log.e(TAG, "onLayout: right = " + left + gridW);
|
||||
// Log.e(TAG, "onLayout: bottom = " + top + gridH);
|
||||
}
|
||||
top += gridH + margin;
|
||||
}
|
||||
}
|
||||
|
||||
public interface GridAdatper {
|
||||
View getView(int index);
|
||||
|
||||
int getCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置适配器
|
||||
*/
|
||||
public void setGridAdapter(GridAdatper adapter) {
|
||||
this.adapter = adapter;
|
||||
// 动态添加视图
|
||||
int size = adapter.getCount();
|
||||
for (int i = 0; i < size; i++) {
|
||||
addView(adapter.getView(i));
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(View v, int index);
|
||||
}
|
||||
|
||||
private ArrayList<DesktopIcon> applicationInfos;
|
||||
|
||||
public void setApplicationInfos(ArrayList<DesktopIcon> infoArrayList) {
|
||||
this.applicationInfos = infoArrayList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置item点击事件
|
||||
*
|
||||
* @param click
|
||||
*/
|
||||
public void setOnItemClickListener(final OnItemClickListener click) {
|
||||
if (this.adapter == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
final int index = i;
|
||||
View view = getChildAt(i);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
click.onItemClick(v, index);
|
||||
}
|
||||
});
|
||||
if (applicationInfos.get(index) == null) {
|
||||
view.setClickable(false);
|
||||
} else {
|
||||
view.setClickable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class RecyclerItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private int itemSpaceLeft;
|
||||
private int itemSpaceCenter;
|
||||
private int itemNum;
|
||||
|
||||
public RecyclerItemDecoration(int itemSpaceLeft, int itemSpaceCenter, int itemNum) {
|
||||
this.itemSpaceLeft = itemSpaceLeft;
|
||||
this.itemSpaceCenter = itemSpaceCenter;
|
||||
this.itemNum = itemNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||
int position = parent.getResources().getDisplayMetrics().widthPixels;
|
||||
//int position = parent.getChildAdapterPosition(view);
|
||||
if (parent.getChildCount() > 0) {
|
||||
if (position % itemNum == 0) { //最左边Item
|
||||
outRect.left = itemSpaceLeft;
|
||||
outRect.right = itemSpaceCenter / 3;
|
||||
} else if (position % itemNum == itemNum - 1) { //最右边Item
|
||||
outRect.left = itemSpaceCenter / 3;
|
||||
outRect.right = itemSpaceLeft;
|
||||
} else { //中间Item
|
||||
outRect.left = itemSpaceCenter / 3;
|
||||
outRect.right = itemSpaceCenter / 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RecyclerViewSpacesItemDecoration extends RecyclerView.ItemDecoration {
|
||||
|
||||
private final HashMap<String, Integer> mSpaceValueMap;
|
||||
|
||||
public static final String TOP_DECORATION = "top_decoration";
|
||||
public static final String BOTTOM_DECORATION = "bottom_decoration";
|
||||
public static final String LEFT_DECORATION = "left_decoration";
|
||||
public static final String RIGHT_DECORATION = "right_decoration";
|
||||
|
||||
public RecyclerViewSpacesItemDecoration(final HashMap<String, Integer> mSpaceValueMap) {
|
||||
this.mSpaceValueMap = mSpaceValueMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(final Rect outRect, final View view, final RecyclerView parent,
|
||||
final RecyclerView.State state) {
|
||||
if (mSpaceValueMap.get(TOP_DECORATION) != null) {
|
||||
outRect.top = mSpaceValueMap.get(TOP_DECORATION);
|
||||
}
|
||||
if (mSpaceValueMap.get(LEFT_DECORATION) != null) {
|
||||
outRect.left = mSpaceValueMap.get(LEFT_DECORATION);
|
||||
}
|
||||
if (mSpaceValueMap.get(RIGHT_DECORATION) != null) {
|
||||
outRect.right = mSpaceValueMap.get(RIGHT_DECORATION);
|
||||
}
|
||||
if (mSpaceValueMap.get(BOTTOM_DECORATION) != null) {
|
||||
outRect.bottom = mSpaceValueMap.get(BOTTOM_DECORATION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
323
app/src/main/java/com/uiui/aios/view/ScaleCircleNavigator.java
Normal file
323
app/src/main/java/com/uiui/aios/view/ScaleCircleNavigator.java
Normal file
@@ -0,0 +1,323 @@
|
||||
package com.uiui.aios.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.util.SparseArray;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import net.lucode.hackware.magicindicator.NavigatorHelper;
|
||||
import net.lucode.hackware.magicindicator.abs.IPagerNavigator;
|
||||
import net.lucode.hackware.magicindicator.buildins.ArgbEvaluatorHolder;
|
||||
import net.lucode.hackware.magicindicator.buildins.UIUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// _oo0oo_
|
||||
// o8888888o
|
||||
// 88" . "88
|
||||
// (| -_- |)
|
||||
// 0\ = /0
|
||||
// ___/`---'\___
|
||||
// .' \\| |// '.
|
||||
// / \\||| : |||// \
|
||||
// / _||||| -:- |||||- \
|
||||
// | | \\\ - /// | |
|
||||
// | \_| ''\---/'' |_/ |
|
||||
// \ .-\__ '-' ___/-. /
|
||||
// ___'. .' /--.--\ `. .'___
|
||||
// ."" '< `.___\_<|>_/___.' >' "".
|
||||
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
|
||||
// \ \ `_. \_ __\ /__ _/ .-` / /
|
||||
// =====`-.____`.___ \_____/___.-`___.-'=====
|
||||
// `=---='
|
||||
//
|
||||
//
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// 佛祖保佑 永无BUG
|
||||
|
||||
/**
|
||||
* 类似CircleIndicator的效果
|
||||
* Created by hackware on 2016/9/3.
|
||||
*/
|
||||
|
||||
public class ScaleCircleNavigator extends View implements IPagerNavigator, NavigatorHelper.OnNavigatorScrollListener {
|
||||
private int mMinRadius;
|
||||
private int mMaxRadius;
|
||||
private int mNormalCircleColor = Color.LTGRAY;
|
||||
private int mSelectedCircleColor = Color.GRAY;
|
||||
private int mCircleSpacing;
|
||||
private int mCircleCount;
|
||||
|
||||
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private List<PointF> mCirclePoints = new ArrayList<PointF>();
|
||||
private SparseArray<Float> mCircleRadiusArray = new SparseArray<Float>();
|
||||
|
||||
// 事件回调
|
||||
private boolean mTouchable;
|
||||
private ScaleCircleNavigator.OnCircleClickListener mCircleClickListener;
|
||||
private float mDownX;
|
||||
private float mDownY;
|
||||
private int mTouchSlop;
|
||||
|
||||
private boolean mFollowTouch = true; // 是否跟随手指滑动
|
||||
private NavigatorHelper mNavigatorHelper = new NavigatorHelper();
|
||||
private Interpolator mStartInterpolator = new LinearInterpolator();
|
||||
|
||||
public ScaleCircleNavigator(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
mMinRadius = UIUtil.dip2px(context, 3);
|
||||
mMaxRadius = UIUtil.dip2px(context, 4);
|
||||
mCircleSpacing = UIUtil.dip2px(context, 8);
|
||||
mNavigatorHelper.setNavigatorScrollListener(this);
|
||||
mNavigatorHelper.setSkimOver(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
|
||||
}
|
||||
|
||||
private int measureWidth(int widthMeasureSpec) {
|
||||
int mode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int result = 0;
|
||||
switch (mode) {
|
||||
case MeasureSpec.EXACTLY:
|
||||
result = width;
|
||||
break;
|
||||
case MeasureSpec.AT_MOST:
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
if (mCircleCount <= 0) {
|
||||
result = getPaddingLeft() + getPaddingRight();
|
||||
} else {
|
||||
result = (mCircleCount - 1) * mMinRadius * 2 + mMaxRadius * 2 + (mCircleCount - 1) * mCircleSpacing + getPaddingLeft() + getPaddingRight();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int measureHeight(int heightMeasureSpec) {
|
||||
int mode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
int result = 0;
|
||||
switch (mode) {
|
||||
case MeasureSpec.EXACTLY:
|
||||
result = height;
|
||||
break;
|
||||
case MeasureSpec.AT_MOST:
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
result = mMaxRadius * 2 + getPaddingTop() + getPaddingBottom();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
for (int i = 0, j = mCirclePoints.size(); i < j; i++) {
|
||||
PointF point = mCirclePoints.get(i);
|
||||
float radius = mCircleRadiusArray.get(i, (float) mMinRadius);
|
||||
mPaint.setColor(ArgbEvaluatorHolder.eval((radius - mMinRadius) / (mMaxRadius - mMinRadius), mNormalCircleColor, mSelectedCircleColor));
|
||||
canvas.drawCircle(point.x, getHeight() / 2.0f, radius, mPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareCirclePoints() {
|
||||
mCirclePoints.clear();
|
||||
if (mCircleCount > 0) {
|
||||
int y = Math.round(getHeight() / 2.0f);
|
||||
int centerSpacing = mMinRadius * 2 + mCircleSpacing;
|
||||
int startX = mMaxRadius + getPaddingLeft();
|
||||
for (int i = 0; i < mCircleCount; i++) {
|
||||
PointF pointF = new PointF(startX, y);
|
||||
mCirclePoints.add(pointF);
|
||||
startX += centerSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (mTouchable) {
|
||||
mDownX = x;
|
||||
mDownY = y;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (mCircleClickListener != null) {
|
||||
if (Math.abs(x - mDownX) <= mTouchSlop && Math.abs(y - mDownY) <= mTouchSlop) {
|
||||
float max = Float.MAX_VALUE;
|
||||
int index = 0;
|
||||
for (int i = 0; i < mCirclePoints.size(); i++) {
|
||||
PointF pointF = mCirclePoints.get(i);
|
||||
float offset = Math.abs(pointF.x - x);
|
||||
if (offset < max) {
|
||||
max = offset;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
mCircleClickListener.onClick(index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
mNavigatorHelper.onPageScrolled(position, positionOffset, positionOffsetPixels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
mNavigatorHelper.onPageSelected(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
mNavigatorHelper.onPageScrollStateChanged(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
prepareCirclePoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
prepareCirclePoints();
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachToMagicIndicator() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachFromMagicIndicator() {
|
||||
}
|
||||
|
||||
public void setMinRadius(int minRadius) {
|
||||
mMinRadius = minRadius;
|
||||
prepareCirclePoints();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setMaxRadius(int maxRadius) {
|
||||
mMaxRadius = maxRadius;
|
||||
prepareCirclePoints();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setNormalCircleColor(int normalCircleColor) {
|
||||
mNormalCircleColor = normalCircleColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setSelectedCircleColor(int selectedCircleColor) {
|
||||
mSelectedCircleColor = selectedCircleColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setCircleSpacing(int circleSpacing) {
|
||||
mCircleSpacing = circleSpacing;
|
||||
prepareCirclePoints();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setStartInterpolator(Interpolator startInterpolator) {
|
||||
mStartInterpolator = startInterpolator;
|
||||
if (mStartInterpolator == null) {
|
||||
mStartInterpolator = new LinearInterpolator();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCircleCount(int count) {
|
||||
mCircleCount = count; // 此处不调用invalidate,让外部调用notifyDataSetChanged
|
||||
mNavigatorHelper.setTotalCount(mCircleCount);
|
||||
}
|
||||
|
||||
public void setTouchable(boolean touchable) {
|
||||
mTouchable = touchable;
|
||||
}
|
||||
|
||||
public void setFollowTouch(boolean followTouch) {
|
||||
mFollowTouch = followTouch;
|
||||
}
|
||||
|
||||
public void setSkimOver(boolean skimOver) {
|
||||
mNavigatorHelper.setSkimOver(skimOver);
|
||||
}
|
||||
|
||||
public void setCircleClickListener(OnCircleClickListener circleClickListener) {
|
||||
if (!mTouchable) {
|
||||
mTouchable = true;
|
||||
}
|
||||
mCircleClickListener = circleClickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnter(int index, int totalCount, float enterPercent, boolean leftToRight) {
|
||||
if (mFollowTouch) {
|
||||
float radius = mMinRadius + (mMaxRadius - mMinRadius) * mStartInterpolator.getInterpolation(enterPercent);
|
||||
mCircleRadiusArray.put(index, radius);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeave(int index, int totalCount, float leavePercent, boolean leftToRight) {
|
||||
if (mFollowTouch) {
|
||||
float radius = mMaxRadius + (mMinRadius - mMaxRadius) * mStartInterpolator.getInterpolation(leavePercent);
|
||||
mCircleRadiusArray.put(index, radius);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelected(int index, int totalCount) {
|
||||
if (!mFollowTouch) {
|
||||
mCircleRadiusArray.put(index, (float) mMaxRadius);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeselected(int index, int totalCount) {
|
||||
if (!mFollowTouch) {
|
||||
mCircleRadiusArray.put(index, (float) mMinRadius);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnCircleClickListener {
|
||||
void onClick(int index);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user