) {
+ for (view in views) {
+ listClearViews.remove(view)
+ }
+ }
+
+ fun removeAllClearViews() {
+ listClearViews.clear()
+ }
+
+ fun setOnClearScreenListener(listener: OnClearScreenListener?) {
+ this.clearScreenListener = listener
+ }
+
+ interface OnClearScreenListener {
+ fun onCleared()
+ fun onRestored()
+ fun isForbidClearScreen(): Boolean = false
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/DividerItemDecoration.java b/app/src/main/java/com/allen/androidcustomview/widget/DividerItemDecoration.java
new file mode 100644
index 0000000..040e988
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/DividerItemDecoration.java
@@ -0,0 +1,117 @@
+package com.allen.androidcustomview.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/02/05
+ * desc : recyclerview的分割线
+ * version : 1.0
+ *
+ */
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+ private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
+
+ public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
+
+ public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
+
+
+ private Drawable mDivider;
+
+ private int mOrientation;
+
+ private Context context;
+
+ public DividerItemDecoration(Context context, int orientation) {
+ final TypedArray a = context.obtainStyledAttributes(ATTRS);
+ mDivider = a.getDrawable(0);
+ this.context = context;
+ a.recycle();
+ setOrientation(orientation);
+ }
+
+ public void setOrientation(int orientation) {
+ if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
+ throw new IllegalArgumentException("invalid orientation");
+ }
+ mOrientation = orientation;
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ super.onDraw(c, parent, state);
+ if (mOrientation == VERTICAL_LIST) {
+ drawVertical(c, parent);
+ } else {
+ drawHorizontal(c, parent);
+ }
+ }
+
+ public void drawVertical(Canvas c, RecyclerView parent) {
+ final int left = parent.getPaddingLeft() + dip2px(context, 0);
+ final int right = parent.getWidth() - parent.getPaddingRight() - dip2px(context, 0);
+
+ final int childCount = parent.getChildCount();
+
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(
+ parent.getContext());
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int top = child.getBottom() + params.bottomMargin;
+ final int bottom = top + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ public void drawHorizontal(Canvas c, RecyclerView parent) {
+ final int top = parent.getPaddingTop();
+ final int bottom = parent.getHeight() - parent.getPaddingBottom();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int left = child.getRight() + params.rightMargin;
+ final int right = left + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ if (mOrientation == VERTICAL_LIST) {
+ outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
+ } else {
+ outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
+ }
+ }
+
+ /**
+ * 单位转换工具类
+ *
+ * @param context 上下文对象
+ * @param dipValue 值
+ * @return 返回值
+ */
+ private int dip2px(Context context, float dipValue) {
+ final float scale = context.getResources().getDisplayMetrics().density;
+ return (int) (dipValue * scale + 0.5f);
+ }
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/HorizontalProgressBar.java b/app/src/main/java/com/allen/androidcustomview/widget/HorizontalProgressBar.java
index e418c2a..e18d347 100644
--- a/app/src/main/java/com/allen/androidcustomview/widget/HorizontalProgressBar.java
+++ b/app/src/main/java/com/allen/androidcustomview/widget/HorizontalProgressBar.java
@@ -345,6 +345,7 @@ public void onAnimationUpdate(ValueAnimator valueAnimator) {
moveDis = currentProgress - tipWidth / 2;
}
invalidate();
+ setCurrentProgress(value);
}
});
progressAnimator.start();
@@ -373,6 +374,15 @@ public HorizontalProgressBar setCurrentProgress(float progress) {
mProgress = progress;
currentProgress = progress * mWidth / 100;
textString = formatNum(format2Int(progress));
+
+ //移动百分比提示框,只有当前进度到提示框中间位置之后开始移动,
+ //当进度框移动到最右边的时候停止移动,但是进度条还可以继续移动
+ //moveDis是tip框移动的距离
+ if (currentProgress >= (tipWidth / 2) &&
+ currentProgress <= (mWidth - tipWidth / 2)) {
+ moveDis = currentProgress - tipWidth / 2;
+ }
+
invalidate();
return this;
}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/HoverItemDecoration.java b/app/src/main/java/com/allen/androidcustomview/widget/HoverItemDecoration.java
new file mode 100644
index 0000000..46570b2
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/HoverItemDecoration.java
@@ -0,0 +1,223 @@
+package com.allen.androidcustomview.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.View;
+
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2018/04/15
+ * desc : 悬停吸顶效果的ItemDecoration
+ * version : 1.0
+ *
+ */
+public class HoverItemDecoration extends RecyclerView.ItemDecoration {
+
+ private Context context;
+
+ private int width;
+
+ /**
+ * 分组item的高度
+ */
+ private int itemHeight;
+ /**
+ * 分割线的高度
+ */
+ private int itemDivideHeight;
+ /**
+ * 分组text距离左边的距离
+ */
+ private int itemTextPaddingLeft;
+
+ /**
+ * 分组item的画笔
+ */
+ private Paint itemPaint;
+ /**
+ * 分组item的颜色
+ */
+ private int itemHoverPaintColor=0xFFf4f4f4;
+ /**
+ * 分组文字的颜色
+ */
+ private int textPaintColor=0xFF999999;
+
+ /**
+ * 悬停item的画笔
+ */
+ private Paint itemHoverPaint;
+ /**
+ * 文字的画笔
+ */
+ private Paint textPaint;
+ /**
+ * 绘制文字的矩形边框
+ */
+ private Rect textRect = new Rect();
+ /**
+ * 分组字母的回调(一般是取的分组的大写字母)
+ */
+ private BindItemTextCallback bindItemTextCallback;
+
+
+ public HoverItemDecoration(Context content, BindItemTextCallback bindItemTextCallback) {
+ this.context = content;
+ this.bindItemTextCallback = bindItemTextCallback;
+
+ width = content.getResources().getDisplayMetrics().widthPixels;
+
+ itemPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ itemPaint.setColor(itemHoverPaintColor);
+
+ itemHoverPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ itemHoverPaint.setColor(itemHoverPaintColor);
+
+ itemHeight = dp2px(30);
+ itemTextPaddingLeft = dp2px(20);
+ itemDivideHeight = dp2px(1);
+
+ textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ textPaint.setColor(textPaintColor);
+ textPaint.setTextSize(sp2px(15));
+
+
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ super.onDraw(c, parent, state);
+ int count = parent.getChildCount();
+ for (int i = 0; i < count; i++) {
+ View view = parent.getChildAt(i);
+ //分组item的顶部和底部
+ int itemTop = view.getTop() - itemHeight;
+ int itemBottom = view.getTop();
+
+ //可见item在adapter中真实的位置
+ int position = parent.getChildAdapterPosition(view);
+
+ //获取回调的分组文字(一般是字母)
+ String text = bindItemTextCallback.getItemText(position);
+
+ //如果是一组中第一个的话绘制出分组的item和文字,否则绘制分割线
+ if (isFirstInGroup(position)) {
+ c.drawRect(0, itemTop, width, itemBottom, itemPaint);
+ drawText(c, itemTop, itemBottom, text);
+ } else {
+ c.drawRect(0, view.getTop() - itemDivideHeight, width, view.getTop(), itemHoverPaint);
+ }
+
+ }
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ super.onDrawOver(c, parent, state);
+ //绘制悬停的view
+
+ int count = parent.getChildCount();
+
+ if (count > 0) {
+ //悬停只是第一个位置悬停,所以只取第一个view进行设置
+ View firstView = parent.getChildAt(0);
+
+ int position = parent.getChildAdapterPosition(firstView);
+ String text = bindItemTextCallback.getItemText(position);
+
+ //如果悬停view的底部小于悬停布局的高度说明正在上滑,就让他随着滑动逐渐滑进去,否则就固定悬停位置不边
+ //isFirstInGroup(position+1)是下一个item是另外分组第一个的时候当前item才滚动上去
+ if (firstView.getBottom() <= itemHeight && isFirstInGroup(position + 1)) {
+ c.drawRect(0, 0, width, firstView.getBottom(), itemHoverPaint);
+ drawText(c, firstView.getBottom() - itemHeight, firstView.getBottom(), text);
+ } else {
+ c.drawRect(0, 0, width, itemHeight, itemHoverPaint);
+ drawText(c, 0, itemHeight, text);
+ }
+ }
+
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ int position = parent.getChildAdapterPosition(view);
+ //如果是分组第一个就留出绘制item的高度
+ if (isFirstInGroup(position)) {
+ outRect.top = itemHeight;
+ }else {
+ outRect.top = itemDivideHeight;
+ }
+
+ }
+
+
+ /**
+ * 绘制文字
+ *
+ * @param canvas 画布
+ */
+ private void drawText(Canvas canvas, int itemTop, int itemBottom, String textString) {
+
+ textRect.left = itemTextPaddingLeft;
+ textRect.top = itemTop;
+ textRect.right = textString.length();
+ textRect.bottom = itemBottom;
+
+ Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
+ int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
+ //文字绘制到整个布局的中心位置
+ canvas.drawText(textString, textRect.left, baseline, textPaint);
+ }
+
+
+ private boolean isFirstInGroup(int position) {
+ if (position == 0) {
+ return true;
+ } else {
+ String prevItemText = bindItemTextCallback.getItemText(position - 1);
+ String currentItemText = bindItemTextCallback.getItemText(position);
+ //上一个和当前位置的值一样说明是同一个组的否则就是新的一组
+ if (prevItemText.equals(currentItemText)) {
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+ }
+
+ public interface BindItemTextCallback {
+ String getItemText(int position);
+ }
+
+ /**
+ * dp 2 px
+ *
+ * @param dpVal
+ */
+ protected int dp2px(int dpVal) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, context.getResources().getDisplayMetrics());
+ }
+
+ /**
+ * sp 2 px
+ *
+ * @param spVal
+ * @return
+ */
+ protected int sp2px(int spVal) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+ spVal, context.getResources().getDisplayMetrics());
+
+ }
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/IndexView.java b/app/src/main/java/com/allen/androidcustomview/widget/IndexView.java
new file mode 100644
index 0000000..17eaa3d
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/IndexView.java
@@ -0,0 +1,154 @@
+package com.allen.androidcustomview.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Created by allen on 2016/10/26.
+ */
+
+public class IndexView extends View {
+
+ private Context mContext;
+ private TextView mShowTextDialog;
+
+
+ private Paint mPaint;
+
+ private int mWidth;
+ private int mHeight;
+
+ private int mCellWidth;
+ private int mCellHeight;
+
+ private int mWordSize;
+ private int mwordColor;
+ private int mChoose = -1;// 选中
+
+
+ private int GRAY = 0xFFe8e8e8;
+ private int DEFAULT_TEXT_COLOR = 0xFF999999;
+
+ private static final String[] WORDS = new String[]{
+ "↑", "☆", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "#"
+ };
+
+ private OnTouchingLetterChangedListener mOnTouchingLetterChangedListener;
+
+ public IndexView(Context context) {
+ this(context, null);
+ }
+
+ public IndexView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public IndexView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mContext = context;
+ mWordSize = sp2px(mContext, 12);
+ mwordColor = 0;
+ initPaint();
+ }
+
+
+ public void setShowTextDialog(TextView textDialog) {
+ this.mShowTextDialog = textDialog;
+ }
+
+ private void initPaint() {
+ mPaint = new Paint();
+ mPaint.setColor(DEFAULT_TEXT_COLOR);
+ mPaint.setAntiAlias(true);
+ mPaint.setTextSize(mWordSize);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mWidth = getMeasuredWidth();
+ mHeight = getMeasuredHeight();
+
+ mCellHeight = mHeight / WORDS.length;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ for (int i = 0; i < WORDS.length; i++) {
+ float xPos = mWidth / 2 - mPaint.measureText(WORDS[i]) / 2;
+ float yPos = mCellHeight * i + mCellHeight;
+ canvas.drawText(WORDS[i], xPos, yPos, mPaint);
+ }
+
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int action = event.getAction();
+ final float y = event.getY();// 点击y坐标
+ final int oldChoose = mChoose;
+ final int c = (int) (y / getHeight() * WORDS.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
+
+
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ setBackgroundColor(0x00000000);
+ mChoose = -1;//
+ invalidate();
+ if (mShowTextDialog != null) {
+ mShowTextDialog.setVisibility(View.INVISIBLE);
+ }
+ break;
+
+ default:
+ setBackgroundColor(GRAY);
+ if (oldChoose != c) {
+ if (c >= 0 && c < WORDS.length) {
+ if (mOnTouchingLetterChangedListener != null) {
+ mOnTouchingLetterChangedListener.onTouchingLetterChanged(WORDS[c]);
+ }
+ if (mShowTextDialog != null) {
+ mShowTextDialog.setText(WORDS[c]);
+ mShowTextDialog.setVisibility(View.VISIBLE);
+ }
+
+ mChoose = c;
+ invalidate();
+ }
+ }
+
+ break;
+ }
+ return true;
+ }
+
+
+ public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener letterChangedListener) {
+ mOnTouchingLetterChangedListener = letterChangedListener;
+
+ }
+
+ public interface OnTouchingLetterChangedListener {
+ void onTouchingLetterChanged(String letter);
+ }
+
+ /**
+ * 文字字体大小sp转换px
+ *
+ * @param context 上下文对象
+ * @param spValue sp的值
+ * @return 返回值
+ */
+ public int sp2px(Context context, float spValue) {
+ final float scale = context.getResources().getDisplayMetrics().scaledDensity;
+ return (int) (spValue * scale + 0.5f);
+ }
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/IndicatorView.java b/app/src/main/java/com/allen/androidcustomview/widget/IndicatorView.java
new file mode 100644
index 0000000..251dad0
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/IndicatorView.java
@@ -0,0 +1,240 @@
+package com.allen.androidcustomview.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/02/27
+ * desc : 首页banner指示器
+ * version : 1.0
+ *
+ */
+
+public class IndicatorView extends View {
+
+ private int mWidth;
+ private int mHeight;
+
+ private float startX;
+
+ /**
+ * 动画起点x坐标
+ */
+ private int centerX;
+
+ /**
+ * 动画起点y坐标
+ */
+ private int centerY;
+
+ /**
+ * view真实高度
+ */
+ private int mViewHeight;
+
+ private int mViewWidth;
+
+ /**
+ * 画笔宽度(等于vie高度)
+ */
+ private int paintWidth;
+
+ private int radius;
+ private int R;
+
+ /**
+ * 圆的颜色
+ */
+ private int circleBgColor = 0xFFCED3D6;
+
+ /**
+ * 当前指示器的颜色
+ */
+ private int currentColor = 0xFFA0946C;
+
+
+ /**
+ * 圆画笔
+ */
+ private Paint circlePaint;
+ /**
+ * 当前指示器的画笔
+ */
+ private Paint indicatorPaint;
+
+
+ private int pointNum = 0;
+ private int currentIndex = 0;
+ /**
+ * 圆之间的间距
+ */
+ private int dis;
+
+ private RectF rectF;
+
+ public IndicatorView(Context context) {
+ this(context, null);
+ }
+
+ public IndicatorView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public IndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ private void init() {
+ rectF = new RectF();
+ paintWidth = dp2px(1);
+ mViewHeight = dp2px(8);
+ radius = dp2px(3);
+ R = 2 * radius;
+ dis = 2 * radius;
+ circlePaint = getPaint(paintWidth, circleBgColor, Paint.Style.FILL);
+ indicatorPaint = getPaint(paintWidth, currentColor, Paint.Style.FILL);
+ }
+
+
+ /**
+ * 统一处理paint
+ *
+ * @param strokeWidth 画笔宽度
+ * @param color 颜色
+ * @param style 风格
+ * @return paint
+ */
+ private Paint getPaint(int strokeWidth, int color, Paint.Style style) {
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setColor(color);
+ paint.setAntiAlias(true);
+ paint.setStyle(style);
+ return paint;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mWidth = w;
+ mHeight = h;
+
+ centerX = w / 2;
+ centerY = h / 2;
+
+ mViewWidth = (2 * pointNum + 1) * R;
+
+ startX = (mWidth - mViewWidth) / 2;
+
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
+ }
+
+ /**
+ * 测量宽度
+ *
+ * @param mode
+ * @param width
+ * @return
+ */
+ private int measureWidth(int mode, int width) {
+ switch (mode) {
+ case MeasureSpec.UNSPECIFIED:
+ case MeasureSpec.AT_MOST:
+ break;
+ case MeasureSpec.EXACTLY:
+ mWidth = width;
+ break;
+ }
+ return mWidth;
+ }
+
+ /**
+ * 测量高度
+ *
+ * @param mode
+ * @param height
+ * @return
+ */
+ private int measureHeight(int mode, int height) {
+ switch (mode) {
+ case MeasureSpec.UNSPECIFIED:
+ case MeasureSpec.AT_MOST:
+ mHeight = mViewHeight;
+ break;
+ case MeasureSpec.EXACTLY:
+ mHeight = height;
+ break;
+ }
+ return mHeight;
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ for (int i = 0; i < pointNum + 1; i++) {
+ drawCircle(canvas, i);
+ }
+ drawCurrentIndicator(canvas, currentIndex);
+ }
+
+
+ private void drawCircle(Canvas canvas, int i) {
+ float x = startX + radius + i * 2 * dis;
+ canvas.drawCircle(x, centerY, radius, circlePaint);
+ }
+
+
+ private void drawCurrentIndicator(Canvas canvas, int i) {
+ float x = startX + 2 * i * dis;
+ rectF.left = x;
+ rectF.top = centerY - radius;
+ rectF.right = x + 3 * dis;
+ rectF.bottom = centerY + radius;
+ canvas.drawRoundRect(rectF, radius, radius, indicatorPaint);
+ }
+
+
+ public IndicatorView setPointNum(int pointNum) {
+ this.pointNum = pointNum;
+ return this;
+ }
+
+ public IndicatorView setCurrentPosition(int position) {
+ currentIndex = position;
+ invalidate();
+ return this;
+ }
+
+ /**
+ * dp 2 px
+ *
+ * @param dpVal dp
+ */
+ protected int dp2px(int dpVal) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, getResources().getDisplayMetrics());
+ }
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/LoadingLineView.java b/app/src/main/java/com/allen/androidcustomview/widget/LoadingLineView.java
new file mode 100644
index 0000000..3cc5214
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/LoadingLineView.java
@@ -0,0 +1,276 @@
+package com.allen.androidcustomview.widget;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * Created by Allen on 2018/1/31.
+ *
+ * 线性加载动画
+ */
+
+public class LoadingLineView extends View {
+
+ private int mWidth;
+ private int mHeight;
+
+ /**
+ * 动画起点x坐标
+ */
+ private int centerX;
+ /**
+ * 动画起点y坐标
+ */
+ private int centerY;
+
+ /**
+ * 偏移距离
+ */
+ private float dis;
+
+ /**
+ * view真实高度
+ */
+ private int mViewHeight;
+
+ /**
+ * 背景色画笔
+ */
+ private Paint bgPaint;
+ /**
+ * loading画笔
+ */
+ private Paint loadingPaint;
+
+ /**
+ * 画笔宽度(等于vie高度)
+ */
+ private int paintWidth;
+
+ /**
+ * 底色
+ */
+ private int bgColor = 0xFFe1e5e8;
+
+ /**
+ * loading颜色
+ */
+ private int loadingColor = 0xFFf66b12;
+
+
+ /**
+ * 动画
+ */
+ private ValueAnimator loadingAnimator;
+ /**
+ * 动画执行时间
+ */
+ private int duration = 800;
+ /**
+ * 动画延时启动时间
+ */
+ private int startDelay = 0;
+
+ /**
+ * 是否停止动画(恢复初始状态)
+ */
+ private boolean isStopAnimation = false;
+
+ public LoadingLineView(Context context) {
+ this(context, null);
+ }
+
+ public LoadingLineView(Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public LoadingLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ getAtt(attrs);
+ init();
+ }
+
+ /**
+ * 想实现颜色等参数可配置,在这里实现配置即可,笔者就不多写了
+ *
+ * @param attrs attrs
+ */
+ private void getAtt(AttributeSet attrs) {
+
+ }
+
+ private void init() {
+ paintWidth = dp2px(2);
+ mViewHeight = paintWidth;
+ bgPaint = getPaint(paintWidth, bgColor, Paint.Style.FILL);
+ loadingPaint = getPaint(paintWidth, loadingColor, Paint.Style.FILL);
+ }
+
+
+ /**
+ * 统一处理paint
+ *
+ * @param strokeWidth 画笔宽度
+ * @param color 颜色
+ * @param style 风格
+ * @return paint
+ */
+ private Paint getPaint(int strokeWidth, int color, Paint.Style style) {
+ Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setColor(color);
+ paint.setAntiAlias(true);
+ paint.setStyle(style);
+ return paint;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mWidth = w;
+ mHeight = h;
+
+ centerX = w / 2;
+ centerY = h / 2;
+
+ initLoadingAnimation();
+ startLoading();
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
+ }
+
+ /**
+ * 测量宽度
+ *
+ * @param mode
+ * @param width
+ * @return
+ */
+ private int measureWidth(int mode, int width) {
+ switch (mode) {
+ case MeasureSpec.UNSPECIFIED:
+ case MeasureSpec.AT_MOST:
+ break;
+ case MeasureSpec.EXACTLY:
+ mWidth = width;
+ break;
+ }
+ return mWidth;
+ }
+
+ /**
+ * 测量高度
+ *
+ * @param mode
+ * @param height
+ * @return
+ */
+ private int measureHeight(int mode, int height) {
+ switch (mode) {
+ case MeasureSpec.UNSPECIFIED:
+ case MeasureSpec.AT_MOST:
+ mHeight = mViewHeight;
+ break;
+ case MeasureSpec.EXACTLY:
+ mHeight = height;
+ break;
+ }
+ return mHeight;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ /**
+ * 画底色
+ */
+ canvas.drawLine(0, centerY, mWidth, centerY, bgPaint);
+
+ if (!isStopAnimation) {
+ /**
+ * loading向左扩散
+ */
+ canvas.drawLine(centerX, centerY, centerX - dis, centerY, loadingPaint);
+ /**
+ * loading向右扩散
+ */
+ canvas.drawLine(centerX, centerY, centerX + dis, centerY, loadingPaint);
+ }
+
+ }
+
+ /**
+ * 初始化动画
+ */
+ private void initLoadingAnimation() {
+ final float loadingMoveDistance = mWidth / 2;
+ loadingAnimator = ValueAnimator.ofFloat(0, loadingMoveDistance);
+ loadingAnimator.setDuration(duration);
+ loadingAnimator.setStartDelay(startDelay);
+ loadingAnimator.setRepeatCount(ValueAnimator.INFINITE);
+ loadingAnimator.setInterpolator(new LinearInterpolator());
+ loadingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ float value = (float) valueAnimator.getAnimatedValue();
+ dis = value;
+ if (value <= loadingMoveDistance / 2) {
+ loadingPaint.setAlpha((int) ((255 * value) * 2 / loadingMoveDistance));
+ } else {
+ loadingPaint.setAlpha((int) (255 - (255 * value) * 2 / loadingMoveDistance));
+ }
+ invalidate();
+ }
+ });
+ }
+
+ /**
+ * 开启动画
+ */
+ public void startLoading() {
+ if (loadingAnimator != null) {
+ loadingAnimator.start();
+ }
+ isStopAnimation = false;
+ }
+
+ /**
+ * 结束动画
+ */
+ public void stopLoading() {
+ if (loadingAnimator != null) {
+ loadingAnimator.cancel();
+ }
+ isStopAnimation = true;
+ invalidate();
+ }
+
+
+ /**
+ * dp 2 px
+ *
+ * @param dpVal dp
+ */
+ protected int dp2px(int dpVal) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, getResources().getDisplayMetrics());
+ }
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/PayPsdInputView.java b/app/src/main/java/com/allen/androidcustomview/widget/PayPsdInputView.java
index 487e040..ce27716 100644
--- a/app/src/main/java/com/allen/androidcustomview/widget/PayPsdInputView.java
+++ b/app/src/main/java/com/allen/androidcustomview/widget/PayPsdInputView.java
@@ -111,6 +111,7 @@ public class PayPsdInputView extends EditText {
*/
private String mComparePassword = null;
+
/**
* 当前输入的位置索引
*/
@@ -279,13 +280,20 @@ protected void onTextChanged(CharSequence text, int start, int lengthBefore, int
this.position = start + lengthAfter;
textLength = text.toString().length();
- if (mComparePassword != null && textLength == maxCount) {
- if (TextUtils.equals(mComparePassword, getPasswordString())) {
- mListener.onEqual(getPasswordString());
- } else {
- mListener.onDifference();
+ if (textLength == maxCount) {
+ if (mListener != null) {
+ if (TextUtils.isEmpty(mComparePassword)) {
+ mListener.inputFinished(getPasswordString());
+ } else {
+ if (TextUtils.equals(mComparePassword, getPasswordString())) {
+ mListener.onEqual(getPasswordString());
+ } else {
+ mListener.onDifference(mComparePassword, getPasswordString());
+ }
+ }
}
}
+
invalidate();
}
@@ -314,12 +322,29 @@ public void setComparePassword(String comparePassword, onPasswordListener listen
mListener = listener;
}
+ public void setComparePassword(onPasswordListener listener) {
+ mListener = listener;
+ }
+
+ public void setComparePassword(String psd) {
+ mComparePassword = psd;
+ }
+
+ /**
+ * 清空密码
+ */
+ public void cleanPsd() {
+ setText("");
+ }
+
/**
* 密码比较监听
*/
public interface onPasswordListener {
- void onDifference();
+ void onDifference(String oldPsd, String newPsd);
void onEqual(String psd);
+
+ void inputFinished(String inputPsd);
}
}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt b/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt
new file mode 100644
index 0000000..468cf0f
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/StudyPlanProgressView.kt
@@ -0,0 +1,163 @@
+package com.allen.androidcustomview.widget
+
+import android.content.Context
+import android.graphics.*
+import android.graphics.drawable.BitmapDrawable
+import android.util.AttributeSet
+import android.util.TypedValue
+import android.view.View
+import com.allen.androidcustomview.R
+import kotlin.math.min
+
+/**
+ *
+ * @author : Allen
+ * date : 2019/08/12
+ * desc : 学习计划view
+ *
+ */
+class StudyPlanProgressView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
+ private var mWidth = 0
+ private var mHeight = 0
+
+ private var iconPaint: Paint? = null
+ private var linePaint: Paint = Paint()
+ private var textPaint: Paint = Paint()
+ private var iconRect = Rect()
+ private var textRectF = Rect()
+
+ private val ALL_POINT_SIZE = 7
+ private var cellWidth = 0
+ private var iconSize = 0
+ private var textSize = 0
+ private var textColor = 0
+ private var progressWidth = 0
+ private var uncheckedProgressColor = Color.GRAY
+ private var checkedProgressColor = Color.YELLOW
+
+ private var iconUncheckedBitmapRes: Bitmap? = null
+ private var iconCheckedBitmapRes: Bitmap? = null
+
+ private var dates: MutableList = mutableListOf()
+
+ private var marginLeftAndRight = 0
+
+ init {
+ marginLeftAndRight = dp2px(27f).toInt()
+ iconSize = dp2px(14f).toInt()
+ initAttr(context, attrs, defStyleAttr)
+ initPaint()
+ }
+
+ private fun initAttr(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
+ val typedArray = context.obtainStyledAttributes(attrs, R.styleable.StudyPlanProgressView)
+ iconUncheckedBitmapRes = (typedArray.getDrawable(R.styleable.StudyPlanProgressView_sppv_iconUnchecked) as? BitmapDrawable)?.bitmap
+ iconCheckedBitmapRes = (typedArray.getDrawable(R.styleable.StudyPlanProgressView_sppv_iconChecked) as? BitmapDrawable)?.bitmap
+ iconSize = typedArray.getDimensionPixelOffset(R.styleable.StudyPlanProgressView_sppv_iconSize, dp2px(14f).toInt())
+ progressWidth = typedArray.getDimensionPixelOffset(R.styleable.StudyPlanProgressView_sppv_progressWidth, dp2px(2f).toInt())
+ uncheckedProgressColor = typedArray.getColor(R.styleable.StudyPlanProgressView_sppv_uncheckedProgressColor, uncheckedProgressColor)
+ checkedProgressColor = typedArray.getColor(R.styleable.StudyPlanProgressView_sppv_checkedProgressColor, checkedProgressColor)
+ textSize = typedArray.getDimensionPixelSize(R.styleable.StudyPlanProgressView_sppv_textSize, sp2px(11))
+ textColor = typedArray.getColor(R.styleable.StudyPlanProgressView_sppv_textColor, checkedProgressColor)
+
+ typedArray.recycle()
+ }
+
+ private fun initPaint() {
+ iconPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ iconPaint?.isFilterBitmap = true
+ iconPaint?.isDither = true
+
+ linePaint.strokeWidth = progressWidth.toFloat()
+ linePaint.color = uncheckedProgressColor
+ linePaint.isAntiAlias = true
+ linePaint.style = Paint.Style.FILL_AND_STROKE
+
+ textPaint.textSize = textSize.toFloat()
+ textPaint.color = textColor
+ textPaint.textAlign = Paint.Align.CENTER
+ textPaint.isAntiAlias = true
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ super.onSizeChanged(w, h, oldw, oldh)
+ mWidth = w
+ mHeight = h
+
+ cellWidth = (mWidth - marginLeftAndRight * 2 - iconSize * ALL_POINT_SIZE) / (ALL_POINT_SIZE - 1)
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ drawProgressLine(canvas)
+ drawProgress(canvas)
+ }
+
+ private fun drawProgressLine(canvas: Canvas) {
+ val lineStart = (marginLeftAndRight + iconSize / 2).toFloat()
+ linePaint.color = uncheckedProgressColor
+ canvas.drawLine(lineStart, (mHeight / 2).toFloat(), (mWidth - marginLeftAndRight - iconSize / 2).toFloat(), (mHeight / 2).toFloat(), linePaint)
+ if (getDataSize() == 0) return
+ val lineEnd = lineStart + (getDataSize() - 1) * (cellWidth + iconSize)
+ linePaint.color = checkedProgressColor
+ canvas.drawLine(lineStart, (mHeight / 2).toFloat(), lineEnd, (mHeight / 2).toFloat(), linePaint)
+ }
+
+ private fun drawProgress(canvas: Canvas) {
+ if (iconUncheckedBitmapRes == null || iconCheckedBitmapRes == null) return
+ for (i in 0 until ALL_POINT_SIZE) {
+ val left = marginLeftAndRight + (cellWidth + iconSize) * i
+ iconRect.set(left, (mHeight - iconSize) / 2, left + iconSize, (mHeight + iconSize) / 2)
+ val bitmap = if (isFinished(i)) iconCheckedBitmapRes else iconUncheckedBitmapRes
+ canvas.drawBitmap(bitmap, null, iconRect, iconPaint)
+ drawText(canvas, i)
+ }
+ }
+
+ private fun isFinished(position: Int): Boolean {
+ return if (position <= getDataSize() - 1) {
+ dates[position].isFinished
+ } else false
+ }
+
+ private fun drawText(canvas: Canvas, position: Int) {
+ if (getDataSize() == 0) return
+ if (position < getDataSize()) {
+ val textWidth = textPaint.measureText(dates[position].content).toInt()
+ val isTop = position % 2 == 0
+ val left = marginLeftAndRight + iconSize / 2 + (cellWidth + iconSize) * position - textWidth / 2
+ textRectF.left = left
+ textRectF.right = left + textWidth
+ textRectF.top = if (isTop) 0 else (mHeight + iconSize) / 2
+ textRectF.bottom = if (isTop) (mHeight - iconSize) / 2 else mHeight
+
+ val fontMetrics = textPaint.fontMetricsInt
+ val baseline = (textRectF.bottom + textRectF.top - fontMetrics.bottom - fontMetrics.top) / 2
+ //文字绘制到整个布局的中心位置
+ canvas.drawText(dates[position].content, textRectF.centerX().toFloat(), baseline.toFloat(), textPaint)
+ }
+ }
+
+ fun setData(date: List?) {
+ dates.clear()
+ val timeList = date?.toMutableList() ?: mutableListOf()
+ timeList.forEach {
+ dates.add(ProgressData(it, true))
+ }
+ invalidate()
+ }
+
+ private fun getDataSize() = min(dates.size, 7)
+
+ fun dp2px(dpVal: Float): Float {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, resources.displayMetrics)
+ }
+
+ fun sp2px(spVal: Int): Int {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+ spVal.toFloat(), resources.displayMetrics).toInt()
+ }
+
+ class ProgressData(var content: String, var isFinished: Boolean)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/SuperDividerItemDecoration.java b/app/src/main/java/com/allen/androidcustomview/widget/SuperDividerItemDecoration.java
new file mode 100644
index 0000000..a7ae5ca
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/SuperDividerItemDecoration.java
@@ -0,0 +1,255 @@
+package com.allen.androidcustomview.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.LinearLayout;
+
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2018/04/15
+ * desc : 万能分割线
+ * version : 1.0
+ *
+ */
+public class SuperDividerItemDecoration extends RecyclerView.ItemDecoration {
+
+
+ public static final int HORIZONTAL = LinearLayout.HORIZONTAL;
+ public static final int VERTICAL = LinearLayout.VERTICAL;
+
+ private static Context context;
+
+
+ /**
+ * 默认分割线的颜色
+ */
+ private int dividerDefaultColor = 0xFFE1E5E8;
+
+ /**
+ * 分割线的颜色
+ */
+ private int dividerColor;
+ /**
+ * 分割线的宽度
+ */
+ private int dividerWidth;
+ /**
+ * 分割线距离左右两边的距离
+ */
+ private int dividerPadding;
+ /**
+ * 分割线距离左边的距离
+ */
+ private int dividerPaddingLeft;
+ /**
+ * 分割线距离右边的距离
+ */
+ private int dividerPaddingRight;
+
+ /**
+ * 分割线距离上边的距离
+ */
+ private int dividerPaddingTop;
+ /**
+ * 分割线距离下边的距离
+ */
+ private int dividerPaddingBottom;
+ /**
+ * 是否显示列表最后一条分割线
+ */
+ private boolean dividerIsShowLastDivide;
+
+
+ /**
+ * 分割线item的画笔
+ */
+ private Paint dividerPaint;
+
+ /**
+ * 分割线开始的位置(解决recyclerView添加头布局的时候,要从header下边的position位置算起)
+ */
+ private int dividerFromPosition = 0;
+
+
+ /**
+ * recyclerView布局方式(水平或者垂直)
+ */
+ private int orientation;
+
+
+ public SuperDividerItemDecoration(Builder builder) {
+
+ context = builder.context;
+
+ dividerColor = builder.dividerColor == 0 ? dividerDefaultColor : builder.dividerColor;
+ dividerPadding = dp2px(builder.dividerPadding);
+ dividerPaddingLeft = dp2px(builder.dividerPaddingLeft);
+ dividerPaddingRight = dp2px(builder.dividerPaddingRight);
+ dividerPaddingTop = dp2px(builder.dividerPaddingTop);
+ dividerPaddingBottom = dp2px(builder.dividerPaddingBottom);
+ dividerWidth = builder.dividerWidth == 0 ? dp2px(0.5f) : dp2px(builder.dividerWidth);
+ dividerFromPosition = builder.dividerFromPosition;
+ dividerIsShowLastDivide = builder.dividerIsShowLastDivide;
+ orientation = builder.orientation;
+ dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ dividerPaint.setColor(dividerColor);
+
+ if (dividerPadding != 0) {
+ dividerPaddingLeft = dividerPaddingRight = dividerPadding;
+ dividerPaddingTop = dividerPaddingBottom = dividerPadding;
+ }
+ }
+
+ public static class Builder {
+
+ private Context context;
+ private int dividerColor;
+ private int dividerWidth;
+ private int dividerPadding;
+ private int dividerPaddingLeft;
+ private int dividerPaddingRight;
+ private int dividerPaddingTop;
+ private int dividerPaddingBottom;
+ private int dividerFromPosition;
+ private boolean dividerIsShowLastDivide;
+ private int orientation = VERTICAL;
+
+ public Builder(Context context) {
+ this.context = context;
+ }
+
+ public Builder setDividerColor(int dividerColor) {
+ this.dividerColor = dividerColor;
+ return this;
+ }
+
+ public Builder setDividerWidth(int dividerWidth) {
+ this.dividerWidth = dividerWidth;
+ return this;
+ }
+
+ public Builder setDividerPadding(int dividerPadding) {
+ this.dividerPadding = dividerPadding;
+ return this;
+ }
+
+ public Builder setDividerPaddingLeft(int dividerPaddingLeft) {
+ this.dividerPaddingLeft = dividerPaddingLeft;
+ return this;
+ }
+
+ public Builder setDividerPaddingRight(int dividerPaddingRight) {
+ this.dividerPaddingRight = dividerPaddingRight;
+ return this;
+ }
+
+ public Builder setDividerPaddingTop(int dividerPaddingTop) {
+ this.dividerPaddingTop = dividerPaddingTop;
+ return this;
+ }
+
+ public Builder setDividerPaddingBottom(int dividerPaddingBottom) {
+ this.dividerPaddingBottom = dividerPaddingBottom;
+ return this;
+ }
+
+ public Builder setDividerFromPosition(int dividerFromPosition) {
+ this.dividerFromPosition = dividerFromPosition;
+ return this;
+ }
+
+ public Builder setIsShowLastDivide(boolean dividerIsShowLastDivide) {
+ this.dividerIsShowLastDivide = dividerIsShowLastDivide;
+ return this;
+ }
+
+ public Builder setOrientation(int orientation) {
+ this.orientation = orientation;
+ return this;
+ }
+
+ public SuperDividerItemDecoration build() {
+ return new SuperDividerItemDecoration(this);
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ super.onDraw(c, parent, state);
+
+ if (orientation == VERTICAL) {
+ drawVertical(c, parent);
+ } else {
+ drawHorizontal(c, parent);
+ }
+
+ }
+
+
+ private void drawVertical(Canvas c, RecyclerView parent) {
+ int count = parent.getChildCount();
+
+ if (count > 0) {
+ int showCount = dividerIsShowLastDivide ? count : count - 1;
+ for (int i = dividerFromPosition; i < showCount; i++) {
+ View view = parent.getChildAt(i);
+ //可见item的底部
+ int itemBottom = view.getBottom();
+
+ c.drawRect(parent.getPaddingLeft() + dividerPaddingLeft,
+ itemBottom,
+ parent.getWidth() - parent.getPaddingRight() - dividerPaddingRight,
+ itemBottom + dividerWidth,
+ dividerPaint);
+ }
+ }
+ }
+
+ private void drawHorizontal(Canvas c, RecyclerView parent) {
+ int count = parent.getChildCount();
+ if (count > 0) {
+ int showCount = dividerIsShowLastDivide ? count : count - 1;
+ for (int i = dividerFromPosition; i < showCount; i++) {
+ View view = parent.getChildAt(i);
+ //可见item的底部
+ int itemRight = view.getRight();
+
+ c.drawRect(itemRight,
+ parent.getPaddingTop() + dividerPaddingTop,
+ itemRight + dividerWidth,
+ parent.getHeight() - parent.getPaddingBottom() - dividerPaddingBottom,
+ dividerPaint);
+ }
+ }
+ }
+
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ if (orientation == VERTICAL) {
+ outRect.bottom = dividerWidth;
+ } else {
+ outRect.right = dividerWidth;
+ }
+ }
+
+ /**
+ * dp 2 px
+ *
+ * @param dpVal
+ */
+ public static int dp2px(float dpVal) {
+ return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, context.getResources().getDisplayMetrics());
+ }
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/BannerView.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/BannerView.java
new file mode 100644
index 0000000..1a5048a
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/BannerView.java
@@ -0,0 +1,173 @@
+package com.allen.androidcustomview.widget.banner;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+import com.allen.androidcustomview.R;
+import com.allen.androidcustomview.widget.banner.adapter.BannerViewPagerAdapter;
+import com.allen.androidcustomview.widget.banner.holder.BannerViewHolderCreator;
+
+import java.util.List;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public class BannerView extends RelativeLayout implements ViewPager.OnPageChangeListener {
+ private static final String TAG = BannerView.class.getSimpleName();
+
+ public ViewPager getViewPager() {
+ return mViewPager;
+ }
+
+ private ViewPager mViewPager;
+ private LinearLayout mIndicatorContainer;
+ private BannerViewPagerAdapter> mAdapter;
+
+ private PagerOptions mPagerOptions;
+ private ImageView mCurrentIndicator;
+
+ public BannerView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public BannerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public BannerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ private void init(Context context) {
+ LayoutInflater.from(context).inflate(R.layout.banner_view_layout, this);
+ mViewPager = (ViewPager) findViewById(R.id.banner_view_pager);
+ mIndicatorContainer = (LinearLayout) findViewById(R.id.banner_indicator_container);
+
+ mPagerOptions = new PagerOptions.Builder(context).build();
+
+ mViewPager.setOffscreenPageLimit(4);
+ mViewPager.addOnPageChangeListener(this);
+ }
+
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ // 切换indicator
+ setIndicatorSelected(position);
+
+ setOnPageSelectedListener(position);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+
+ }
+
+
+ private void setOnPageSelectedListener(int position) {
+ if (mPagerOptions.mOnPageChangeListener != null) {
+ mPagerOptions.mOnPageChangeListener.onPageSelected(position);
+ }
+ }
+
+ /**
+ * 设置 PagerOptions
+ *
+ * @param options options
+ * @return BannerPager
+ */
+ public BannerView setPagerOptions(PagerOptions options) {
+ mPagerOptions = options;
+ return this;
+ }
+
+ /**
+ * 设置 page data
+ *
+ * @param data List
+ * @param creator BannerViewHolderCreator
+ */
+ public void setPages(@NonNull List> data, @NonNull BannerViewHolderCreator creator) {
+ if (data == null || creator == null) {
+ return;
+ }
+ mAdapter = new BannerViewPagerAdapter<>(data, creator);
+
+ initIndicator();
+ handlePagerOptions();
+
+ mViewPager.setAdapter(mAdapter);
+
+
+ }
+
+ private void initIndicator() {
+
+ int count = mAdapter.getRealCount();
+
+ mIndicatorContainer.removeAllViews();
+ ImageView indicator;
+ LinearLayout.LayoutParams layoutParams;
+
+ for (int i = 0; i < count; i++) {
+ layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ layoutParams.setMargins(10,0,10,0);
+ indicator = new ImageView(getContext());
+ indicator.setImageDrawable(mPagerOptions.mIndicatorDrawable[0]);
+ indicator.setLayoutParams(layoutParams);
+ mIndicatorContainer.addView(indicator);
+ }
+ setIndicatorSelected(mViewPager.getCurrentItem());
+
+ }
+
+ private void setIndicatorSelected(int currentItem) {
+ if (mCurrentIndicator != null) {
+ mCurrentIndicator.setImageDrawable(mPagerOptions.mIndicatorDrawable[0]);
+ mCurrentIndicator.setSelected(false);
+ }
+ if (mIndicatorContainer.getChildCount()>0){
+ final ImageView indicator = (ImageView) mIndicatorContainer.getChildAt(currentItem);
+ indicator.setSelected(true);
+ indicator.setImageDrawable(mPagerOptions.mIndicatorDrawable[1]);
+ mCurrentIndicator = indicator;
+ }
+ }
+
+ private void handlePagerOptions() {
+ //设置每页之间间距
+ mViewPager.setPageMargin(mPagerOptions.mPageMargin);
+ //设置预显示宽
+ final ViewGroup.MarginLayoutParams mp = (MarginLayoutParams) mViewPager.getLayoutParams();
+ mp.leftMargin = mp.rightMargin = mPagerOptions.mPrePagerWidth;
+ mViewPager.setLayoutParams(mp);
+
+ //设置切换效果
+ mViewPager.setPageTransformer(true, mPagerOptions.mPageTransformer);
+ mAdapter.setPageClickListener(mPagerOptions.mOnPageClickListener);
+
+ }
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/PagerOptions.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/PagerOptions.java
new file mode 100644
index 0000000..9a68aee
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/PagerOptions.java
@@ -0,0 +1,259 @@
+package com.allen.androidcustomview.widget.banner;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.DrawableRes;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.view.ViewPager;
+import android.util.TypedValue;
+
+import com.allen.androidcustomview.widget.banner.listener.OnPageChangeListener;
+import com.allen.androidcustomview.widget.banner.listener.OnPageClickListener;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public class PagerOptions {
+
+
+ int mPageMargin;
+ int mPrePagerWidth;
+ int mIndicatorVisibility;
+ Drawable[] mIndicatorDrawable;
+ int mIndicatorDistance;
+ boolean mLoopEnable;
+ int mDelayedTime;
+ int mIndicatorAlign;
+ ViewPager.PageTransformer mPageTransformer;
+ int mScrollDuration;
+ int mIndicatorMarginBottom;
+ int mIndicatorSize;
+ OnPageClickListener mOnPageClickListener;
+ OnPageChangeListener mOnPageChangeListener;
+
+ private PagerOptions() {
+ }
+
+ public static class Builder {
+
+ private Context mContext;
+ private int mPageMargin;
+ private int mPrePagerWidth;
+ private int mIndicatorAlign;
+ private int mIndicatorVisibility;
+ private Drawable[] mIndicatorDrawable = new Drawable[2];
+ private int mIndicatorDistance = 8;
+ private boolean mLoopEnable = true;
+ private ViewPager.PageTransformer mPageTransformer;
+ private int mDelayedTime = 3000;
+ private int mScrollDuration = 800;
+ private int mIndicatorMarginBottom = -1;
+ private int mIndicatorSize = -1;
+ private OnPageClickListener mOnPageClickListener;
+ private OnPageChangeListener mOnPageChangeListener;
+
+ public Builder(Context context) {
+ mContext = context;
+ //设置默认指示器
+// setIndicatorDrawable(R.drawable.indicator_normal_default, R.drawable.indicator_selected_default);
+ }
+
+
+ /**
+ * 设置每个 page 之间间隔
+ *
+ * @param px px value
+ * @return Builder
+ */
+ public Builder setPageMargin(int px) {
+ mPageMargin = px;
+ return this;
+ }
+
+ /**
+ * 左右两侧预显示宽度
+ *
+ * @param px px value
+ * @return Builder
+ */
+ public Builder setPrePagerWidth(int px) {
+ mPrePagerWidth = px;
+ return this;
+ }
+
+ /**
+ * 设置指示器间距
+ *
+ * @param distance px value
+ * @return Builder
+ */
+ public Builder setIndicatorDistance(int distance) {
+ mIndicatorDistance = distance;
+ return this;
+ }
+
+ /**
+ * 设置指示器距离底部间距
+ *
+ * @param marginBottom marginBottom
+ * @return Builder
+ */
+ public Builder setIndicatorMarginBottom(int marginBottom) {
+ mIndicatorMarginBottom = marginBottom;
+ return this;
+ }
+
+ /**
+ * 设置指示器位置
+ *
+ * @param align RelativeLayout.ALIGN_PARENT_LEFT || RelativeLayout.CENTER_IN_PARENT || RelativeLayout.ALIGN_PARENT_RIGHT
+ * @return Builder
+ */
+ public Builder setIndicatorAlign(int align) {
+ mIndicatorAlign = align;
+ return this;
+ }
+
+ /**
+ * 设置Indicator 是否可见
+ *
+ * @param visibility One of VISIBLE, INVISIBLE, GONE.
+ * @return Builder
+ */
+ public Builder setIndicatorVisibility(int visibility) {
+ mIndicatorVisibility = visibility;
+ return this;
+ }
+
+ /**
+ * 设置轮播切换效果
+ *
+ * @param transformer PageTransformer
+ * @return Builder
+ */
+ public Builder setPageTransformer(ViewPager.PageTransformer transformer) {
+ mPageTransformer = transformer;
+ return this;
+ }
+
+ /**
+ * 设置指示器
+ *
+ * @param unSelected 未选中
+ * @param selected 选中
+ * @return Builder
+ */
+ public Builder setIndicatorDrawable(@DrawableRes int unSelected, @DrawableRes int selected) {
+ mIndicatorDrawable[0] = ContextCompat.getDrawable(mContext, unSelected);
+ mIndicatorDrawable[1] = ContextCompat.getDrawable(mContext, selected);
+ return this;
+ }
+
+ /**
+ * 设置指示器
+ *
+ * @param unSelected 未选中
+ * @param selected 选中
+ * @return Builder
+ */
+ public Builder setIndicatorColor(@ColorInt int unSelected, @ColorInt int selected) {
+ mIndicatorDrawable[0] = createDrawable(unSelected);
+ mIndicatorDrawable[1] = createDrawable(selected);
+ return this;
+ }
+
+ private Drawable createDrawable(@ColorInt int color) {
+ final int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, mContext.getResources().getDisplayMetrics());
+ final GradientDrawable gd = new GradientDrawable();
+ gd.setColor(color);
+ gd.setShape(GradientDrawable.OVAL);
+ gd.setSize(size, size);
+ return gd;
+ }
+
+ /**
+ * 设置指示器
+ *
+ * @param size px
+ * @return Builder
+ */
+ public Builder setIndicatorSize(int size) {
+ mIndicatorSize = size;
+ return this;
+ }
+
+ /**
+ * 设置可否循环
+ *
+ * @param loop loop
+ * @return Builder
+ */
+ public Builder setLoopEnable(boolean loop) {
+ mLoopEnable = loop;
+ return this;
+ }
+
+ /**
+ * 设置切换时间
+ *
+ * @param duration ms
+ * @return Builder
+ */
+ public Builder setTurnDuration(int duration) {
+ mDelayedTime = duration;
+ return this;
+ }
+
+ /**
+ * 设置ViewPager的滚动速度
+ *
+ * @param duration ms
+ */
+ public Builder setScrollDuration(int duration) {
+ mScrollDuration = duration;
+ return this;
+ }
+
+
+ public Builder setOnPageClickListener(OnPageClickListener onPageClickListener) {
+ this.mOnPageClickListener = onPageClickListener;
+ return this;
+ }
+
+ public Builder setOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
+ this.mOnPageChangeListener = onPageChangeListener;
+ return this;
+ }
+
+ public PagerOptions build() {
+ final PagerOptions options = new PagerOptions();
+
+ options.mPageMargin = mPageMargin;
+ options.mPrePagerWidth = mPrePagerWidth;
+ options.mIndicatorDistance = mIndicatorDistance;
+ options.mIndicatorDrawable = mIndicatorDrawable;
+ options.mIndicatorSize = mIndicatorSize;
+ options.mIndicatorAlign = mIndicatorAlign;
+ options.mIndicatorVisibility = mIndicatorVisibility;
+ options.mLoopEnable = mLoopEnable;
+ options.mPageTransformer = mPageTransformer;
+ options.mDelayedTime = mDelayedTime;
+ options.mScrollDuration = mScrollDuration;
+ options.mIndicatorMarginBottom = mIndicatorMarginBottom;
+ options.mOnPageClickListener = mOnPageClickListener;
+ options.mOnPageChangeListener = mOnPageChangeListener;
+ mContext = null;
+ return options;
+ }
+ }
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/adapter/BannerViewPagerAdapter.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/adapter/BannerViewPagerAdapter.java
new file mode 100644
index 0000000..2a14a6d
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/adapter/BannerViewPagerAdapter.java
@@ -0,0 +1,122 @@
+package com.allen.androidcustomview.widget.banner.adapter;
+
+import android.support.annotation.NonNull;
+import android.support.v4.view.PagerAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.allen.androidcustomview.widget.banner.listener.OnPageClickListener;
+import com.allen.androidcustomview.widget.banner.holder.BannerViewHolder;
+import com.allen.androidcustomview.widget.banner.holder.BannerViewHolderCreator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public class BannerViewPagerAdapter extends PagerAdapter {
+
+ private List mData;
+ private BannerViewHolderCreator mCreator;
+ private OnPageClickListener mPageClickListener;
+
+ public BannerViewPagerAdapter(@NonNull List data, @NonNull BannerViewHolderCreator creator) {
+
+ if (mData == null) {
+ mData = new ArrayList<>();
+ }
+ mData = data;
+ mCreator = creator;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, final int position) {
+ View view = getView(position, container);
+ container.addView(view);
+ return view;
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ container.removeView((View) object);
+ }
+
+
+
+ /**
+ * 获取真实的Count
+ *
+ * @return
+ */
+ public int getRealCount() {
+ return mData == null ? 0 : mData.size();
+ }
+
+ @Override
+ public int getCount() {
+ return getRealCount();
+ }
+
+ /**
+ * @param position
+ * @param container
+ * @return
+ */
+ private View getView(int position, ViewGroup container) {
+
+ final int realPosition = position % getRealCount();
+ BannerViewHolder holder = null;
+ // create holder
+ holder = mCreator.createViewHolder();
+
+ if (holder == null) {
+ throw new RuntimeException("can not return a null holder");
+ }
+ // create View
+ View view = holder.createView(container.getContext());
+
+ if (mData != null && mData.size() > 0) {
+ holder.onBind(container.getContext(), realPosition, mData.get(realPosition));
+ }
+
+ // 添加page点击事件
+ if (view != null) {
+ view.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mPageClickListener != null) {
+ mPageClickListener.onPageClick(v, realPosition);
+ }
+ }
+ });
+ }
+
+ return view;
+ }
+
+
+ public List getData() {
+ return mData;
+ }
+
+ public void setData(List mData) {
+ this.mData = mData;
+ }
+
+ public void setPageClickListener(OnPageClickListener pageClickListener) {
+ this.mPageClickListener = pageClickListener;
+ }
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolder.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolder.java
new file mode 100644
index 0000000..35165dd
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolder.java
@@ -0,0 +1,33 @@
+package com.allen.androidcustomview.widget.banner.holder;
+
+import android.content.Context;
+import android.view.View;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public interface BannerViewHolder {
+
+ /**
+ * 创建View
+ * @param context
+ * @return
+ */
+ View createView(Context context);
+
+ /**
+ * 绑定数据
+ * @param context
+ * @param position
+ * @param data
+ */
+ void onBind(Context context, int position, T data);
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolderCreator.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolderCreator.java
new file mode 100644
index 0000000..5192566
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/holder/BannerViewHolderCreator.java
@@ -0,0 +1,20 @@
+package com.allen.androidcustomview.widget.banner.holder;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public interface BannerViewHolderCreator {
+ /**
+ * 创建 BannerViewHolder
+ *
+ * @return BannerViewHolder
+ */
+ VH createViewHolder();
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageChangeListener.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageChangeListener.java
new file mode 100644
index 0000000..521f52d
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageChangeListener.java
@@ -0,0 +1,21 @@
+package com.allen.androidcustomview.widget.banner.listener;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/09
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public interface OnPageChangeListener {
+
+ /**
+ * item 选中事件
+ *
+ * @param position position
+ */
+ void onPageSelected(int position);
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageClickListener.java b/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageClickListener.java
new file mode 100644
index 0000000..e1ac8cd
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageClickListener.java
@@ -0,0 +1,25 @@
+package com.allen.androidcustomview.widget.banner.listener;
+
+import android.view.View;
+
+/**
+ *
+ * @author : xiaoyao
+ * e-mail : xiaoyao@51vest.com
+ * date : 2018/03/02
+ * desc :
+ * version : 1.0
+ *
+ */
+
+public interface OnPageClickListener {
+
+ /**
+ * item 点击事件
+ *
+ * @param view view
+ * @param position position
+ */
+ void onPageClick(View view, int position);
+
+}
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/status/StatusBuilder.kt b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusBuilder.kt
new file mode 100644
index 0000000..a036c92
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusBuilder.kt
@@ -0,0 +1,50 @@
+package com.allen.androidcustomview.widget.status
+
+import android.view.View
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2019/03/19
+ * desc :
+ *
+ */
+class StatusBuilder {
+
+ class Builder{
+
+ var contentView: View? = null
+ var errorView: View? = null
+ var emptyView: View? = null
+ var loadingView: View? = null
+
+ fun setContentView(contentView: View):Builder {
+ this.contentView = contentView
+ return this
+ }
+ fun setContentView(layoutResId: Int):Builder {
+ this.contentView = contentView
+ return this
+ }
+
+ fun setErrorView(errorView: View):Builder {
+ this.errorView = errorView
+ return this
+ }
+
+ fun setEmptyView(emptyView: View):Builder {
+ this.emptyView = emptyView
+ return this
+ }
+
+ fun setLoadingView(loadingView: View):Builder {
+ this.loadingView = loadingView
+ return this
+ }
+
+ fun build(){
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/status/StatusLayout.kt b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusLayout.kt
new file mode 100644
index 0000000..470b9bc
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusLayout.kt
@@ -0,0 +1,27 @@
+package com.allen.androidcustomview.widget.status
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2019/03/19
+ * desc : 状态布局
+ *
+ */
+
+class StatusLayout : FrameLayout {
+
+ constructor(context: Context) : this(context, null)
+ constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
+ initAttrs(attrs)
+ }
+
+ private fun initAttrs(attrs: AttributeSet?) {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/status/StatusManager.kt b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusManager.kt
new file mode 100644
index 0000000..383baf7
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/status/StatusManager.kt
@@ -0,0 +1,29 @@
+package com.allen.androidcustomview.widget.status
+
+/**
+ *
+ * @author : Allen
+ * e-mail : lygttpod@163.com
+ * date : 2019/03/19
+ * desc :
+ *
+ */
+object StatusManager {
+
+
+ fun setEmptyView(){
+
+ }
+
+ fun setErrorView(){
+
+ }
+
+ fun setContentView() {
+
+ }
+
+ fun setLoadingView() {
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteContainerView.kt b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteContainerView.kt
new file mode 100644
index 0000000..9cf7f2c
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteContainerView.kt
@@ -0,0 +1,283 @@
+package com.allen.androidcustomview.widget.vote
+
+import android.content.Context
+import android.graphics.Outline
+import android.os.Build
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewOutlineProvider
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import android.widget.Toast
+import com.allen.androidcustomview.R
+import com.allen.androidcustomview.bean.VoteBean
+import com.allen.androidcustomview.bean.VoteOption
+import kotlinx.android.synthetic.main.widget_vote_layout.view.*
+import java.lang.ref.WeakReference
+
+/**
+ *
+ * @author : Allen
+ * date : 2019/08/01
+ * desc :
+ *
+ */
+class VoteContainerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : FrameLayout(context, attrs, defStyleAttr) {
+
+ private var voteViewHolders: ArrayList = arrayListOf()
+
+ var onVoteClickListener: OnVoteClickListener? = null
+
+ companion object {
+ val VOTE_TYPE_MULTIPLE = "multiple"
+ val VOTE_TYPE_SINGLE = "single"
+ }
+
+ private var optionIds = arrayListOf()
+
+ private var mData: VoteBean? = null
+
+ init {
+ initView()
+ }
+
+ private fun initView() {
+ LayoutInflater.from(context).inflate(R.layout.widget_vote_layout, this)
+
+ vote_container_vote_btn.setOnClickListener {
+ if (mData == null) return@setOnClickListener
+ onVoteClickListener?.onVoteCommitBtnClick(mData, optionIds)
+ }
+ }
+
+ fun setVoteData(data: VoteBean?) {
+ if (data == null || data.options.isNullOrEmpty()) {
+ visibility = View.GONE
+ } else {
+ mData = data
+ setVoteTitle(data.title)
+ voteViewHolders.clear()
+ optionIds.clear()
+ setVoteStatus(data)
+ setVoteBtnStatus()
+ vote_item_ll.removeAllViews()
+ data.options?.forEachIndexed { index, voteOption ->
+ val viewHolder = onCreateViewHolder()
+ viewHolder.bind(index, voteOption, data)
+ voteViewHolders.add(viewHolder)
+ vote_item_ll.addView(viewHolder.voteView)
+ }
+ }
+ }
+
+ private fun setVoteTitle(title: String?) {
+ vote_container_title.text = title ?: ""
+ }
+
+ private fun setVoteStatus(vote: VoteBean) {
+ val isVoteMulti = vote.choiceType == VOTE_TYPE_MULTIPLE
+ val voteResult = vote.sumVoteCount ?: 0
+ val voted = vote.voted
+ vote_container_vote_btn.visibility = if (voted != true && isVoteMulti) View.VISIBLE else View.GONE
+ vote_container_vote_result.visibility = if (voted == true) View.VISIBLE else View.GONE
+ setVoteResult("共${voteResult}人参与了投票")
+ }
+
+ private fun addOptionIds(id: Int) {
+ optionIds.add(id)
+ }
+
+
+ private fun removeOptionIds(id: Int) {
+ optionIds.remove(id)
+ }
+
+ private fun getOptionIdsSize(): Int {
+ return optionIds.size
+ }
+
+ private fun setVoteBtnStatus() {
+ val clickable = getOptionIdsSize() > 0
+ if (clickable) {
+ vote_container_vote_btn.setBackgroundResource(R.drawable.shape_bg_clickable)
+ } else {
+ vote_container_vote_btn.setBackgroundResource(R.drawable.shape_bg_un_clickable)
+ }
+ vote_container_vote_btn.isClickable = clickable
+ }
+
+ fun refreshDataAfterVoteSuccess() {
+ vote_container_vote_result.visibility = View.VISIBLE
+ vote_container_vote_btn.visibility = View.GONE
+ refreshVoteResult()
+ startProgressAnim()
+ }
+
+ fun refreshDataAfterVoteFailed() {
+ voteViewHolders.forEach {
+ it.resetDataAfterSingleVoteFailed()
+ }
+ }
+
+ fun onDestroy() {
+ voteViewHolders.forEach {
+ it.onVoteDestroy()
+ }
+ }
+
+ private fun refreshVoteResult() {
+ val voteResult = (mData?.sumVoteCount ?: 0)
+ setVoteResult("共${(voteResult + 1)}人参与了投票")
+ }
+
+ private fun setVoteResult(result: String?) {
+ vote_container_vote_result.text = result ?: ""
+ }
+
+ private fun startProgressAnim() {
+ voteViewHolders.forEach {
+ it.setProgress()
+ }
+ }
+
+ private fun onCreateViewHolder(): VoteItemViewHolder {
+ return VoteItemViewHolder(getVoteView(context), this)
+ }
+
+ class VoteItemViewHolder(var voteView: VoteView, voteContainerView: VoteContainerView) {
+
+ private val voteContainerViewRef = WeakReference(voteContainerView)
+
+ private fun ref(): VoteContainerView? {
+ return voteContainerViewRef.get()
+ }
+
+ private var data: VoteOption? = null
+ private var mainVote: VoteBean? = null
+
+ var isVoteMulti = true
+
+ fun bind(position: Int, voteOption: VoteOption, mainVote: VoteBean) {
+ this.data = voteOption
+ this.mainVote = mainVote
+
+ isVoteMulti = mainVote.choiceType == VOTE_TYPE_MULTIPLE
+
+ val voteResultCount = voteOption.showCount ?: 0
+
+ voteView.setVoteIsSelected(voteOption.voted ?: false)
+ .setVoteContent(voteOption.content)
+ .setVoteResultText("${voteResultCount}人").refreshView()
+
+ if (isHaveVoted()) {
+ val sum = mainVote?.sumVoteCount ?: 0
+ val showCount = data?.showCount ?: 0
+ val progress = if (sum == 0) 0f else showCount.toFloat() / sum.toFloat()
+
+ voteView.setProgress(progress)
+ }
+
+ voteView.setOnClickListener {
+ if (isHaveVoted()) return@setOnClickListener
+ if (isVoteMulti) {
+ setMultiChoice(voteView, voteOption)
+ ref()?.onVoteClickListener?.onVoteItemClick(mainVote, data)
+ } else {
+ if (ref()?.getOptionIdsSize() ?: 0 > 0) return@setOnClickListener
+ setSingleChoice(voteView, voteOption)
+ ref()?.onVoteClickListener?.onVoteItemClick(mainVote, data)
+ }
+ }
+
+ }
+
+ private fun isHaveVoted(): Boolean {
+ return mainVote?.voted ?: false
+ }
+
+ fun setProgress() {
+ val sum = mainVote?.sumVoteCount ?: 0
+ var showCount = data?.showCount ?: 0
+ val realShowCount = if (data?.voted == true) showCount + 1 else showCount
+ voteView.setVoteResultText("${realShowCount}人")
+ mainVote?.voted = true
+ val progress = if (sum == 0) 0f else realShowCount.toFloat() / sum.toFloat()
+ voteView.setProgressWithAnim(progress)
+ }
+
+ fun resetDataAfterSingleVoteFailed() {
+ if (isVoteMulti) return
+ data?.voted = false
+ ref()?.removeOptionIds(data?.id ?: 0)
+ voteView.setVoteIsSelected(data?.voted ?: false).refreshView()
+ }
+
+ fun onVoteDestroy() {
+ voteView.onDestroy()
+ }
+
+ private fun setMultiChoice(voteView: VoteView, voteOption: VoteOption) {
+ if (voteOption.voted == true) {
+ voteOption.voted = false
+ ref()?.removeOptionIds(voteOption.id ?: 0)
+ } else {
+ val optionsIdSize = ref()?.optionIds?.size ?: 0
+ val maxSelect = mainVote?.maxSelect ?: 0
+ if (optionsIdSize < maxSelect) {
+ voteOption.voted = true
+ ref()?.addOptionIds(voteOption.id ?: 0)
+ } else {
+ Toast.makeText(ref()?.context, "最多可选${maxSelect}个", Toast.LENGTH_SHORT).show()
+ }
+ }
+ ref()?.setVoteBtnStatus()
+ voteView.setVoteIsSelected(voteOption.voted ?: false).refreshView()
+ }
+
+ private fun setSingleChoice(voteView: VoteView, voteOption: VoteOption) {
+ voteOption.voted = true
+ ref()?.addOptionIds(voteOption.id ?: 0)
+ voteView.setVoteIsSelected(voteOption.voted ?: false).refreshView()
+ ref()?.onVoteClickListener?.onVoteCommitBtnClick(mainVote, ref()?.optionIds
+ ?: arrayListOf())
+ }
+
+ }
+
+ private fun getVoteView(context: Context): VoteView {
+ val voteView = VoteView(context)
+ voteView.setVoteTextSize(voteView.sp2px(15))
+ .setVoteUncheckedContentTextColor(resources.getColor(R.color.unchecked_content_text_color))
+ .setVoteCheckedContentTextColor(resources.getColor(R.color.checked_content_text_color))
+ .setVoteUncheckedResultTextColor(resources.getColor(R.color.unchecked_result_text_color))
+ .setVoteCheckedResultTextColor(resources.getColor(R.color.checked_result_text_color))
+ .setVoteUncheckedProgressColor(resources.getColor(R.color.unchecked_progress_color))
+ .setVoteCheckedProgressColor(resources.getColor(R.color.checked_progress_color))
+ .setVoteCheckedIcon(resources.getDrawable(R.mipmap.icon_vote_check))
+ .setVoteBorderRadius(voteView.dp2px(3f))
+ .setVoteBorderColor(resources.getColor(R.color.border_color))
+ .setVoteRightIconSize(voteView.dp2px(18f).toInt())
+ .setVoteAnimDuration(2000L)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ voteView.clipToOutline = true
+ voteView.outlineProvider = object : ViewOutlineProvider() {
+ override fun getOutline(view: View, outline: Outline) {
+ outline.setRoundRect(0, 0, view.width, view.height, voteView.dp2px(3f))
+ }
+ }
+ }
+
+ val layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, voteView.dp2px(40f).toInt())
+ layoutParams.bottomMargin = voteView.dp2px(12f).toInt()
+ voteView.layoutParams = layoutParams
+ return voteView
+ }
+
+
+ interface OnVoteClickListener {
+ fun onVoteCommitBtnClick(mainVote: VoteBean?, optionIds: ArrayList)
+ fun onVoteItemClick(mainVote: VoteBean?, voteOption: VoteOption?)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteLayoutAdapter.kt b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteLayoutAdapter.kt
new file mode 100644
index 0000000..95a7eca
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteLayoutAdapter.kt
@@ -0,0 +1,89 @@
+package com.allen.androidcustomview.widget.vote
+
+import android.view.View
+import android.view.ViewGroup
+import com.allen.androidcustomview.bean.VoteBean
+import com.allen.androidcustomview.bean.VoteOption
+import java.lang.ref.WeakReference
+
+/**
+ *
+ * @author : Allen
+ * date : 2019/08/03
+ * desc :
+ *
+ */
+class VoteLayoutAdapter(private val viewGroup: ViewGroup) {
+
+ private var viewHolders = mutableListOf()
+
+ var onVoteClickListener: OnVoteClickListener? = null
+
+ fun setData(vote: ArrayList?) {
+ viewGroup.removeAllViews()
+ viewHolders.clear()
+ if (vote == null || vote.size <= 0) {
+ viewGroup.visibility = View.GONE
+ } else {
+ viewGroup.visibility = View.VISIBLE
+ val size = vote.size
+ for (i in 0 until size) {
+ val viewHolder = onCreateViewHolder(viewGroup, i)
+ viewHolder.bind(vote[i])
+ viewHolders.add(viewHolder)
+ viewGroup.addView(viewHolder.voteContainerView)
+ }
+ }
+ }
+
+ fun refreshDataAfterVotedSuccess(position: Int) {
+ viewHolders[position].voteContainerView.refreshDataAfterVoteSuccess()
+ }
+
+ fun refreshDataAfterVotedFailed(position: Int) {
+ viewHolders[position].voteContainerView.refreshDataAfterVoteFailed()
+ }
+
+ fun onDestroy() {
+ viewHolders.forEach {
+ it.voteContainerView.onDestroy()
+ }
+ }
+
+ private fun onCreateViewHolder(viewGroup: ViewGroup, position: Int): VoteViewHolder {
+ val view = VoteContainerView(viewGroup.context)
+ return VoteViewHolder(view, this, position)
+ }
+
+ class VoteViewHolder(view: VoteContainerView, adapter: VoteLayoutAdapter, var position: Int) {
+
+ private val adapterRef = WeakReference(adapter)
+ private fun ref(): VoteLayoutAdapter? {
+ return adapterRef.get()
+ }
+
+ var voteContainerView = view
+ private var mMainVote: VoteBean? = null
+
+ fun bind(mainVote: VoteBean) {
+ mMainVote = mainVote
+ voteContainerView.setVoteData(mainVote)
+ voteContainerView.onVoteClickListener = object : VoteContainerView.OnVoteClickListener {
+ override fun onVoteCommitBtnClick(mainVote: VoteBean?, optionIds: ArrayList) {
+ ref()?.onVoteClickListener?.onVoteCommitBtnClick(mainVote, optionIds, position)
+ }
+
+ override fun onVoteItemClick(mainVote: VoteBean?, voteOption: VoteOption?) {
+ ref()?.onVoteClickListener?.onVoteItemClick(mainVote, voteOption, position)
+ }
+
+ }
+ }
+
+ }
+
+ interface OnVoteClickListener {
+ fun onVoteCommitBtnClick(mainVote: VoteBean?, optionIds: ArrayList, position: Int)
+ fun onVoteItemClick(mainVote: VoteBean?, voteOption: VoteOption?, position: Int)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteView.kt b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteView.kt
new file mode 100644
index 0000000..7a0845c
--- /dev/null
+++ b/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteView.kt
@@ -0,0 +1,419 @@
+package com.allen.androidcustomview.widget.vote
+
+import android.animation.ValueAnimator
+import android.content.Context
+import android.graphics.*
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.util.TypedValue
+import android.view.View
+import android.view.animation.DecelerateInterpolator
+import com.allen.androidcustomview.R
+import kotlin.math.max
+
+/**
+ *
+ * @author : Allen
+ * date : 2019/07/30
+ * desc :
+ *
+ */
+class VoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
+
+ private var mWidth = 0
+ private var mHeight = 0
+
+ private var bgRectF = RectF()
+ private var progressRectF = RectF()
+ private var voteContentRectF = Rect()
+ private var voteResultRectF = Rect()
+ private var voteRightIconRectF = Rect()
+
+ private var voteResultBaseline = 0
+ private var voteContentBaseline = 0
+
+ private var progressPaint: Paint? = null
+ private var iconPaint: Paint? = null
+ private var bgPaint: Paint? = null
+ private var borderPaint: Paint? = null
+
+ private var voteContentTextPaint: Paint? = null
+ private var voteResultTextPaint: Paint? = null
+
+ private var animDuration = 1000L
+
+ private var mScale = 1f
+
+ private var mProgress = -1f
+ private var mVoteContent: String? = null
+ private var mVoteResult: String? = null
+
+ private var valueAnimator: ValueAnimator? = null
+
+ private var textMarginLeft = 0
+ private var voteResultMarginRight = 0
+
+ private var textPaintSize: Int = 0
+
+ private var rightCheckedBitmapRes: Bitmap? = null
+
+ private var rightIconWidth = 0
+ private var rightIconHeight = 0
+
+ private var checkedProgressColor = 0
+ private var unCheckedProgressColor = 0
+
+ private var checkedContentTextColor = 0
+ private var uncheckedContentTextColor = 0
+
+ private var checkedResultTextColor = 0
+ private var uncheckedResultTextColor = 0
+
+ private var borderColor = 0
+ private var borderRadius = 0f
+
+ private var isVoteChecked = false
+ private var textWidth = 0
+
+ private val defaultCheckedProgressColor = Color.argb(1, 255, 124, 5)
+ private val defaultUncheckedProgressColor = Color.parseColor("#F3F3F3")
+ private val defaultCheckedTextColor = Color.parseColor("#FF7C05")
+ private val defaultUncheckedTextColor = Color.parseColor("#1a1a1a")
+ private val defaultBorderColor = Color.parseColor("#e6e6e6")
+
+ init {
+
+ textMarginLeft = dp2px(15f).toInt()
+ voteResultMarginRight = dp2px(15f).toInt()
+
+ initAttr(context, attrs, defStyleAttr)
+
+ initPaint()
+
+ initVoteRightIcon()
+
+ initColor()
+ }
+
+ private fun initColor() {
+ voteContentTextPaint?.color = if (isVoteChecked) checkedContentTextColor else uncheckedContentTextColor
+ voteResultTextPaint?.color = if (isVoteChecked) checkedResultTextColor else uncheckedResultTextColor
+ progressPaint?.color = if (isVoteChecked) checkedProgressColor else unCheckedProgressColor
+ bgPaint?.color = if (isVoteChecked) checkedProgressColor else unCheckedProgressColor
+ }
+
+ private fun initVoteRightIcon() {
+ if (rightCheckedBitmapRes != null) {
+ if (rightIconWidth == 0 || rightIconHeight == 0) {
+ rightIconWidth = dp2px(36f).toInt()
+ rightIconHeight = dp2px(36f).toInt()
+ }
+ }
+ }
+
+ private fun initAttr(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
+ val typedArray = context.obtainStyledAttributes(attrs, R.styleable.VoteView)
+
+ checkedProgressColor = typedArray.getColor(R.styleable.VoteView_voteCheckedProgressColor, defaultCheckedProgressColor)
+ unCheckedProgressColor = typedArray.getColor(R.styleable.VoteView_voteUncheckedProgressColor, defaultUncheckedProgressColor)
+
+ checkedContentTextColor = typedArray.getColor(R.styleable.VoteView_voteCheckedContentTextColor, defaultCheckedTextColor)
+ uncheckedContentTextColor = typedArray.getColor(R.styleable.VoteView_voteUncheckedContentTextColor, defaultUncheckedTextColor)
+
+ checkedResultTextColor = typedArray.getColor(R.styleable.VoteView_voteCheckedResultTextColor, defaultCheckedTextColor)
+ uncheckedResultTextColor = typedArray.getColor(R.styleable.VoteView_voteUncheckedResultTextColor, defaultUncheckedTextColor)
+
+ textPaintSize = typedArray.getDimensionPixelSize(R.styleable.VoteView_voteTextSize, sp2px(15))
+
+ borderColor = typedArray.getColor(R.styleable.VoteView_voteBorderColor, defaultBorderColor)
+ borderRadius = typedArray.getDimensionPixelOffset(R.styleable.VoteView_voteBorderRadius, dp2px(1f).toInt()).toFloat()
+
+ animDuration = typedArray.getInt(R.styleable.VoteView_voteAnimDuration, 500).toLong()
+
+ rightCheckedBitmapRes = (typedArray.getDrawable(R.styleable.VoteView_voteCheckedIcon) as? BitmapDrawable)?.bitmap
+
+ rightIconWidth = typedArray.getDimensionPixelOffset(R.styleable.VoteView_voteRightIconWidth, 0)
+ rightIconHeight = typedArray.getDimensionPixelOffset(R.styleable.VoteView_voteRightIconHeight, 0)
+
+ typedArray.recycle()
+ }
+
+ private fun initPaint() {
+ iconPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ iconPaint?.isFilterBitmap = true
+ iconPaint?.isDither = true
+
+ bgPaint = getPaint(dp2px(0.5f), Color.WHITE, Paint.Style.FILL)
+ progressPaint = getPaint(dp2px(0.5f), unCheckedProgressColor, Paint.Style.FILL)
+ borderPaint = getPaint(dp2px(0.5f), borderColor, Paint.Style.STROKE)
+
+ voteContentTextPaint = getTextPaint(uncheckedContentTextColor, textPaintSize.toFloat())
+ voteResultTextPaint = getTextPaint(uncheckedResultTextColor, textPaintSize.toFloat())
+ }
+
+ private fun getPaint(strokeWidth: Float, color: Int, style: Paint.Style): Paint {
+ val paint = Paint(Paint.ANTI_ALIAS_FLAG)
+ paint.strokeWidth = strokeWidth
+ paint.color = color
+ paint.isAntiAlias = true
+ paint.style = style
+ return paint
+ }
+
+ private fun getTextPaint(color: Int, textSize: Float): Paint {
+ val textPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ textPaint.textSize = textSize
+ textPaint.color = color
+ textPaint.textAlign = Paint.Align.CENTER
+ textPaint.isAntiAlias = true
+// textPaint.typeface = Typeface.DEFAULT_BOLD
+ return textPaint
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ super.onSizeChanged(w, h, oldw, oldh)
+ mWidth = w
+ mHeight = h
+
+ setBgRect()
+ setProgressRect()
+
+ setVoteResultRect()
+ setVoteContentRect()
+ setVoteRightIconRect()
+
+ }
+
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+
+ drawBg(canvas)
+ drawProgress(canvas)
+ drawBorder(canvas)
+
+ drawVoteContentText(canvas)
+ drawVoteResultText(canvas)
+ drawVoteRightIcon(canvas)
+ }
+
+
+ private fun setBgRect() {
+ bgRectF.set(0f, 0f, mWidth.toFloat(), mHeight.toFloat())
+ }
+
+ private fun setProgressRect() {
+ progressRectF.set(0f, 0f, 0f, mHeight.toFloat())
+ }
+
+ private fun setVoteResultRect() {
+ if (mVoteResult.isNullOrBlank()) return
+ voteResultTextPaint!!.getTextBounds(mVoteResult, 0, mVoteResult!!.length, voteResultRectF)
+
+ voteResultRectF.top = 0
+ voteResultRectF.bottom = mHeight
+
+ val fontMetrics = voteResultTextPaint!!.fontMetricsInt
+ voteResultBaseline = (voteResultRectF.bottom + voteResultRectF.top - fontMetrics.bottom - fontMetrics.top) / 2
+ }
+
+ private fun setVoteContentRect() {
+ if (mVoteContent.isNullOrBlank()) return
+ voteContentTextPaint!!.getTextBounds(mVoteContent, 0, mVoteContent!!.length, voteContentRectF)
+
+ textWidth = (voteContentRectF.right - voteContentRectF.left)
+ voteContentRectF.top = 0
+ voteContentRectF.bottom = mHeight
+ voteContentRectF.left = (mWidth - textWidth) / 2
+ voteContentRectF.right = voteContentRectF.left + textWidth
+
+ val fontMetrics = voteContentTextPaint!!.fontMetricsInt
+ voteContentBaseline = (voteContentRectF.bottom + voteContentRectF.top - fontMetrics.bottom - fontMetrics.top) / 2
+ }
+
+ private fun setVoteRightIconRect() {
+ voteRightIconRectF.set(voteContentRectF.right + voteResultMarginRight, (mHeight - rightIconHeight) / 2, voteContentRectF.right + voteResultMarginRight + rightIconWidth, (mHeight + rightIconHeight) / 2)
+ }
+
+
+ private fun drawBg(canvas: Canvas) {
+ if (mProgress != -1f) {
+ bgPaint?.color = Color.WHITE
+ }
+ canvas.drawRoundRect(bgRectF, 0f, 0f, bgPaint!!)
+ }
+
+ private fun drawProgress(canvas: Canvas) {
+ if (mProgress == -1f) return
+ canvas.drawRoundRect(getProgressRectF(), 0f, 0f, progressPaint!!)
+ }
+
+ private fun drawBorder(canvas: Canvas) {
+ borderPaint?.color = borderColor
+ canvas.drawRoundRect(bgRectF, borderRadius, borderRadius, borderPaint)
+ }
+
+ private fun drawVoteContentText(canvas: Canvas) {
+ if (mVoteContent.isNullOrBlank()) return
+ //文字绘制到整个布局的中心位置
+ if (mProgress == -1f) {
+ voteContentRectF.left = (mWidth - textWidth) / 2
+ voteContentRectF.right = voteContentRectF.left + textWidth
+ } else {
+ voteContentRectF.left = max(((1 - mScale) * (mWidth - textWidth) / 2).toInt(), textMarginLeft)
+ voteContentRectF.right = voteContentRectF.left + textWidth
+ }
+
+ canvas.drawText(mVoteContent, voteContentRectF.centerX().toFloat(), voteContentBaseline.toFloat(), voteContentTextPaint)
+ }
+
+ private fun drawVoteResultText(canvas: Canvas) {
+ if (mProgress == -1f || mVoteResult.isNullOrBlank()) return
+ //文字绘制到整个布局的中心位置
+ voteResultTextPaint?.alpha = (255 * mScale).toInt()
+ canvas.drawText(mVoteResult, mWidth - voteResultMarginRight - voteResultRectF.centerX().toFloat(), voteResultBaseline.toFloat(), voteResultTextPaint)
+ }
+
+ private fun drawVoteRightIcon(canvas: Canvas) {
+ if (rightCheckedBitmapRes != null && isVoteChecked) {
+ voteRightIconRectF.left = voteContentRectF.right + voteResultMarginRight
+ voteRightIconRectF.right = voteRightIconRectF.left + rightIconWidth
+ canvas.drawBitmap(rightCheckedBitmapRes!!, null, voteRightIconRectF, iconPaint)
+ }
+ }
+
+ private fun getProgressRectF(): RectF {
+// val currentProgress = mProgress * mWidth * mScale / 100
+ val currentProgress = mProgress * mWidth * mScale
+ progressRectF.set(0f, 0f, currentProgress, mHeight.toFloat())
+ return progressRectF
+ }
+
+
+ fun setVoteCheckedProgressColor(color: Int): VoteView {
+ this.checkedProgressColor = color
+ return this
+ }
+
+ fun setVoteUncheckedProgressColor(color: Int): VoteView {
+ this.unCheckedProgressColor = color
+ return this
+ }
+
+ fun setVoteBorderRadius(radius: Float): VoteView {
+ this.borderRadius = radius
+ return this
+ }
+
+ fun setVoteBorderColor(color: Int): VoteView {
+ this.borderColor = color
+ return this
+ }
+
+ fun setVoteCheckedContentTextColor(color: Int): VoteView {
+ this.checkedContentTextColor = color
+ return this
+ }
+
+ fun setVoteUncheckedContentTextColor(color: Int): VoteView {
+ this.uncheckedContentTextColor = color
+ return this
+ }
+
+
+ fun setVoteCheckedResultTextColor(color: Int): VoteView {
+ this.checkedResultTextColor = color
+ return this
+ }
+
+ fun setVoteUncheckedResultTextColor(color: Int): VoteView {
+ this.uncheckedResultTextColor = color
+ return this
+ }
+
+ fun setVoteCheckedIcon(iconBitmap: Drawable): VoteView {
+ this.rightCheckedBitmapRes = (iconBitmap as? BitmapDrawable)?.bitmap
+ return this
+ }
+
+ fun setVoteRightIconSize(width_height: Int): VoteView {
+ this.rightIconWidth = width_height
+ this.rightIconHeight = width_height
+ return this
+ }
+
+ fun setVoteTextSize(textSize: Int): VoteView {
+ this.textPaintSize = textSize
+ return this
+ }
+
+ fun setVoteAnimDuration(duration: Long): VoteView {
+ this.animDuration = duration
+ return this
+ }
+
+ fun setVoteContent(content: String?): VoteView {
+ mVoteContent = content ?: ""
+ setVoteContentRect()
+ return this
+ }
+
+ fun setVoteResultText(voteResult: String?): VoteView {
+ mVoteResult = voteResult ?: ""
+ setVoteResultRect()
+ return this
+ }
+
+ fun refreshView() {
+ initColor()
+ invalidate()
+ }
+
+
+ fun setProgress(progress: Float) {
+ mProgress = progress
+ if (mProgress != -1f) {
+ invalidate()
+ }
+ }
+
+ fun setProgressWithAnim(progress: Float) {
+ mProgress = progress
+ startAnim()
+ }
+
+ private fun startAnim() {
+ valueAnimator?.cancel()
+ if (valueAnimator == null) {
+ valueAnimator = ValueAnimator.ofFloat(0f, 1f)
+ }
+ valueAnimator?.duration = animDuration
+ valueAnimator?.interpolator = DecelerateInterpolator()
+ valueAnimator?.addUpdateListener {
+ mScale = it.animatedValue as Float
+ invalidate()
+ }
+ valueAnimator?.start()
+ }
+
+ fun onDestroy() {
+ valueAnimator?.cancel()
+ valueAnimator = null
+ }
+
+ fun setVoteIsSelected(isVoteSelected: Boolean): VoteView {
+ this.isVoteChecked = isVoteSelected
+ return this
+ }
+
+ fun dp2px(dpVal: Float): Float {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ dpVal, resources.displayMetrics)
+ }
+
+ fun sp2px(spVal: Int): Int {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+ spVal.toFloat(), resources.displayMetrics).toInt()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_bg_clickable.xml b/app/src/main/res/drawable/shape_bg_clickable.xml
new file mode 100644
index 0000000..5994224
--- /dev/null
+++ b/app/src/main/res/drawable/shape_bg_clickable.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_bg_un_clickable.xml b/app/src/main/res/drawable/shape_bg_un_clickable.xml
new file mode 100644
index 0000000..902bdea
--- /dev/null
+++ b/app/src/main/res/drawable/shape_bg_un_clickable.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_circle_bg.xml b/app/src/main/res/drawable/shape_circle_bg.xml
new file mode 100644
index 0000000..5c92444
--- /dev/null
+++ b/app/src/main/res/drawable/shape_circle_bg.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_item_bg.xml b/app/src/main/res/drawable/shape_item_bg.xml
new file mode 100644
index 0000000..a15600f
--- /dev/null
+++ b/app/src/main/res/drawable/shape_item_bg.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_search.xml b/app/src/main/res/drawable/shape_search.xml
new file mode 100644
index 0000000..b45f287
--- /dev/null
+++ b/app/src/main/res/drawable/shape_search.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/shape_vote_item_bg.xml b/app/src/main/res/drawable/shape_vote_item_bg.xml
new file mode 100644
index 0000000..594eaf2
--- /dev/null
+++ b/app/src/main/res/drawable/shape_vote_item_bg.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_alipay_home.xml b/app/src/main/res/layout/activity_alipay_home.xml
new file mode 100644
index 0000000..ff55fd7
--- /dev/null
+++ b/app/src/main/res/layout/activity_alipay_home.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_banner.xml b/app/src/main/res/layout/activity_banner.xml
new file mode 100644
index 0000000..7cfb9df
--- /dev/null
+++ b/app/src/main/res/layout/activity_banner.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_clear_screen.xml b/app/src/main/res/layout/activity_clear_screen.xml
new file mode 100644
index 0000000..675b590
--- /dev/null
+++ b/app/src/main/res/layout/activity_clear_screen.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_hover_item.xml b/app/src/main/res/layout/activity_hover_item.xml
new file mode 100644
index 0000000..8530110
--- /dev/null
+++ b/app/src/main/res/layout/activity_hover_item.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 6c6a5df..0df5fab 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,76 +1,13 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="match_parent" />
+
diff --git a/app/src/main/res/layout/activity_path.xml b/app/src/main/res/layout/activity_path.xml
new file mode 100644
index 0000000..338c4f9
--- /dev/null
+++ b/app/src/main/res/layout/activity_path.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_pay_psd_view.xml b/app/src/main/res/layout/activity_pay_psd_view.xml
index 01a8df9..d3481b0 100644
--- a/app/src/main/res/layout/activity_pay_psd_view.xml
+++ b/app/src/main/res/layout/activity_pay_psd_view.xml
@@ -5,14 +5,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:paddingTop="50dp"
tools:context="com.allen.androidcustomview.activity.PayPsdViewActivity">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_reveal_animation.xml b/app/src/main/res/layout/activity_reveal_animation.xml
new file mode 100644
index 0000000..63ba912
--- /dev/null
+++ b/app/src/main/res/layout/activity_reveal_animation.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_sina_vote.xml b/app/src/main/res/layout/activity_sina_vote.xml
new file mode 100644
index 0000000..cb60371
--- /dev/null
+++ b/app/src/main/res/layout/activity_sina_vote.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/adapter_item_hover_user.xml b/app/src/main/res/layout/adapter_item_hover_user.xml
new file mode 100644
index 0000000..1054cef
--- /dev/null
+++ b/app/src/main/res/layout/adapter_item_hover_user.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/adapter_item_main.xml b/app/src/main/res/layout/adapter_item_main.xml
new file mode 100644
index 0000000..eac4730
--- /dev/null
+++ b/app/src/main/res/layout/adapter_item_main.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/banner_item.xml b/app/src/main/res/layout/banner_item.xml
new file mode 100644
index 0000000..d6b4566
--- /dev/null
+++ b/app/src/main/res/layout/banner_item.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/banner_view_layout.xml b/app/src/main/res/layout/banner_view_layout.xml
new file mode 100644
index 0000000..f2cf4a4
--- /dev/null
+++ b/app/src/main/res/layout/banner_view_layout.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/include_default_layout.xml b/app/src/main/res/layout/include_default_layout.xml
new file mode 100644
index 0000000..f5eb9ea
--- /dev/null
+++ b/app/src/main/res/layout/include_default_layout.xml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/include_toolbar_close.xml b/app/src/main/res/layout/include_toolbar_close.xml
new file mode 100644
index 0000000..1348361
--- /dev/null
+++ b/app/src/main/res/layout/include_toolbar_close.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/include_toolbar_open.xml b/app/src/main/res/layout/include_toolbar_open.xml
new file mode 100644
index 0000000..2703831
--- /dev/null
+++ b/app/src/main/res/layout/include_toolbar_open.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_danmu_layout.xml b/app/src/main/res/layout/item_danmu_layout.xml
new file mode 100644
index 0000000..0906697
--- /dev/null
+++ b/app/src/main/res/layout/item_danmu_layout.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_vote_layout.xml b/app/src/main/res/layout/widget_vote_layout.xml
new file mode 100644
index 0000000..38cef29
--- /dev/null
+++ b/app/src/main/res/layout/widget_vote_layout.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
index cde69bc..3c9de7c 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
index c133a0c..9df99a2 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_study_progress_completed.png b/app/src/main/res/mipmap-mdpi/icon_study_progress_completed.png
new file mode 100755
index 0000000..cb766a8
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_study_progress_completed.png differ
diff --git a/app/src/main/res/mipmap-mdpi/icon_study_progress_not_check.png b/app/src/main/res/mipmap-mdpi/icon_study_progress_not_check.png
new file mode 100755
index 0000000..0d68f56
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/icon_study_progress_not_check.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index bfa42f0..250a0ac 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/alipay_home_bg.jpg b/app/src/main/res/mipmap-xxhdpi/alipay_home_bg.jpg
new file mode 100644
index 0000000..50e6bcf
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/alipay_home_bg.jpg differ
diff --git a/app/src/main/res/mipmap-xxhdpi/banner_point_disabled.png b/app/src/main/res/mipmap-xxhdpi/banner_point_disabled.png
new file mode 100644
index 0000000..9399d3c
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/banner_point_disabled.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/banner_point_enabled.png b/app/src/main/res/mipmap-xxhdpi/banner_point_enabled.png
new file mode 100644
index 0000000..fcc9db8
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/banner_point_enabled.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/car.png b/app/src/main/res/mipmap-xxhdpi/car.png
new file mode 100644
index 0000000..2b1fc47
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/car.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_add.png b/app/src/main/res/mipmap-xxhdpi/ic_add.png
new file mode 100644
index 0000000..4d563a8
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_add.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_camera_3x.png b/app/src/main/res/mipmap-xxhdpi/ic_camera_3x.png
new file mode 100644
index 0000000..e5d04a1
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_camera_3x.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_card.png b/app/src/main/res/mipmap-xxhdpi/ic_card.png
new file mode 100644
index 0000000..626fa18
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_card.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_contact.png b/app/src/main/res/mipmap-xxhdpi/ic_contact.png
new file mode 100644
index 0000000..802747b
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_contact.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 324e72c..8bcfa9d 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_payment.png b/app/src/main/res/mipmap-xxhdpi/ic_payment.png
new file mode 100644
index 0000000..7b6b4cc
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_payment.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_scan.png b/app/src/main/res/mipmap-xxhdpi/ic_scan.png
new file mode 100644
index 0000000..7be7b64
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_scan.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_search.png b/app/src/main/res/mipmap-xxhdpi/ic_search.png
new file mode 100644
index 0000000..02c7f68
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_search.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_transfer.png b/app/src/main/res/mipmap-xxhdpi/ic_transfer.png
new file mode 100644
index 0000000..db41da5
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_transfer.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_img1.png b/app/src/main/res/mipmap-xxhdpi/icon_img1.png
new file mode 100644
index 0000000..64f74aa
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_img1.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_img2.jpg b/app/src/main/res/mipmap-xxhdpi/icon_img2.jpg
new file mode 100644
index 0000000..663ce32
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_img2.jpg differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_vote_check.png b/app/src/main/res/mipmap-xxhdpi/icon_vote_check.png
new file mode 100755
index 0000000..64d7c8a
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_vote_check.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/icon_vote_unchecked.png b/app/src/main/res/mipmap-xxhdpi/icon_vote_unchecked.png
new file mode 100755
index 0000000..ee844a2
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/icon_vote_unchecked.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg b/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg
new file mode 100644
index 0000000..b29c7f6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/live_bg.jpeg differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index aee44e1..a1fe6ba 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 9791d5b..a43a62b 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -10,7 +10,7 @@
-
+
@@ -29,8 +29,8 @@
-
-
+
+
@@ -59,4 +59,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index c677974..5a8852d 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -19,4 +19,21 @@
#80FF7E37
#80EB4438
+ #ffffff
+ #1983d1
+ #11222222
+
+
+ #e6e6e6
+ #1AFF7C05
+ #F3F3F3
+ #1a1a1a
+ #FF7C05
+ #333333
+ #FF7C05
+
+ #333333
+ #E2E2E2
+ #FFD500
+
diff --git a/build.gradle b/build.gradle
index 74b2ab0..270f05a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.4.21'
repositories {
jcenter()
+ google()
+ mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.3'
+ classpath 'com.android.tools.build:gradle:4.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -15,6 +19,9 @@ buildscript {
allprojects {
repositories {
jcenter()
+ maven { url "https://jitpack.io" }
+ google()
+ mavenCentral()
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 04e285f..6533050 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Dec 28 10:00:20 PST 2015
+#Mon May 14 16:20:08 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
\ No newline at end of file