android 六边形简书,水波浪贝塞尔效果(六边形)
先看效果
image.png
代码
/**
* 六边形水位效果
*/
public class SixWave extends View {
private static final float DEFAULT_AMPLITUDE_RATIO = 0.1f;
private static final float DEFAULT_AMPLITUDE_VALUE = 50.0f;
private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;
private static final int DEFAULT_WAVE_PROGRESS_VALUE = 50;
private static final int DEFAULT_WAVE_COLOR = Color.parseColor("#212121");
private static final int DEFAULT_WAVE_BACKGROUND_COLOR = Color.parseColor("#00000000");
private static final float DEFAULT_BORDER_WIDTH = 0;
private int mCanvasSize;
private float mAmplitudeRatio;//振幅度比列大小
private int mWaveBgColor;
private int mWaveColor;
private float mDefaultWaterLevel;//默认水位等级
private float mWaterLevelRatio = 1f;//变速等级
private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;//变速比率
private int mProgressValue = DEFAULT_WAVE_PROGRESS_VALUE;//进度
private BitmapShader mWaveShader;//水位渲染
private Matrix mShaderMatrix;//矩阵着色
private Paint mWavePaint;
private Paint mWaveBgPaint;
private Paint mBorderPaint;
private ObjectAnimator waveShiftAnim;//执行动画
private AnimatorSet mAnimatorSet;//动画组合 用来控制 暂停开始
private Context mContext;
public SixWave(final Context context) {
this(context, null);
}
public SixWave(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SixWave(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
mContext = context;
mShaderMatrix = new Matrix();
mWavePaint = new Paint();
mWavePaint.setAntiAlias(true);
mWaveBgPaint = new Paint();
mWaveBgPaint.setAntiAlias(true);
initAnimation();
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.SixWave, defStyleAttr, 0);
mWaveColor = attributes.getColor(R.styleable.SixWave_sw_waveColor, DEFAULT_WAVE_COLOR);
mWaveBgColor = attributes.getColor(R.styleable.SixWave_sw_wave_background_Color, DEFAULT_WAVE_BACKGROUND_COLOR);
mWaveBgPaint.setColor(mWaveBgColor);
float amplitudeRatioAttr = attributes.getFloat(R.styleable.SixWave_sw_waveAmplitude, DEFAULT_AMPLITUDE_VALUE) / 1000;
mAmplitudeRatio = (amplitudeRatioAttr > DEFAULT_AMPLITUDE_RATIO) ? DEFAULT_AMPLITUDE_RATIO : amplitudeRatioAttr;
mProgressValue = attributes.getInteger(R.styleable.SixWave_sw_progressValue, DEFAULT_WAVE_PROGRESS_VALUE);
setProgressValue(mProgressValue);
mBorderPaint = new Paint();
mBorderPaint.setAntiAlias(true);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(attributes.getDimension(R.styleable.SixWave_sw_borderWidth, dp2px(DEFAULT_BORDER_WIDTH)));
mBorderPaint.setColor(attributes.getColor(R.styleable.SixWave_sw_borderColor, DEFAULT_WAVE_COLOR));
attributes.recycle();
}
@Override
public void onDraw(Canvas canvas) {
mCanvasSize = canvas.getWidth();
if (canvas.getHeight() < mCanvasSize) {
mCanvasSize = canvas.getHeight();
}
if (mWaveShader != null) {
if (mWavePaint.getShader() == null) {
mWavePaint.setShader(mWaveShader);
}
mShaderMatrix.setScale(1, mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO, 0, mDefaultWaterLevel);
mShaderMatrix.postTranslate(mWaveShiftRatio * getWidth(),
(DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());
mWaveShader.setLocalMatrix(mShaderMatrix);
//六边形主要代码
drawPolygon(canvas);
} else {
mWavePaint.setShader(null);
}
}
private void drawPolygon(Canvas canvas) {
Path path = new Path();
float radius, centerX, centerY;
radius = centerX = centerY = Math.min(getWidth(), getHeight()) * 0.5f;
radius -= getBorderWidth() * 0.5f;
float offsetAngle = 0;
offsetAngle = (float) (Math.PI * offsetAngle / 180);
for (int i = 0; i < getSides(); i++) {
float x = (float) (centerX + radius * Math.cos(offsetAngle));
float y = (float) (centerY + radius * Math.sin(offsetAngle));
offsetAngle += 2 * Math.PI / getSides();
if (i == 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
path.close();
if (getSides() % 2 != 0) {
Matrix mMatrix = new Matrix();
mMatrix.postRotate(-90, centerX, centerY);
path.transform(mMatrix);
}
canvas.drawPath(path, mBorderPaint);
canvas.drawPath(path, mWavePaint);
}
private int getSides() {
return 6;//6边形
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCanvasSize = w;
if (h < mCanvasSize) mCanvasSize = h;
updateWaveShader();
}
/**
* 初始动画
*/
private void initAnimation() {
waveShiftAnim = ObjectAnimator.ofFloat(this, "waveShiftRatio", 0f, 1f);
waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);
waveShiftAnim.setDuration(1000);
waveShiftAnim.setInterpolator(new LinearInterpolator());
mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(waveShiftAnim);
}
/**
* 进度值动画
*
* @param progress
*/
public void setProgressValue(int progress) {
mProgressValue = progress;
ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(this, "waterLevelRatio", mWaterLevelRatio, ((float) mProgressValue / 100));
waterLevelAnim.setDuration(1000);
waterLevelAnim.setInterpolator(new DecelerateInterpolator());
AnimatorSet animatorSetProgress = new AnimatorSet();
animatorSetProgress.play(waterLevelAnim);
animatorSetProgress.start();
}
/*
大波浪
*/
private void updateWaveShader() {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (width > 0 && height > 0) {
double defaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / width;
float defaultAmplitude = height * DEFAULT_AMPLITUDE_RATIO;
mDefaultWaterLevel = height * DEFAULT_WATER_LEVEL_RATIO;
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint wavePaint = new Paint();
wavePaint.setStrokeWidth(2);
wavePaint.setAntiAlias(true);
final int endX = width + 1;
final int endY = height + 1;
float[] waveY = new float[endX];
wavePaint.setColor(adjustAlpha(mWaveColor, 0.3f));
for (int beginX = 0; beginX < endX; beginX++) {
double wx = beginX * defaultAngularFrequency;
float beginY = (float) (mDefaultWaterLevel + defaultAmplitude * Math.sin(wx));
canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);
waveY[beginX] = beginY;
}
wavePaint.setColor(mWaveColor);
final int wave2Shift = (int) ((float) width / 4);
for (int beginX = 0; beginX < endX; beginX++) {
canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
}
mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
this.mWavePaint.setShader(mWaveShader);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureWidth(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
int imageSize = (width < height) ? width : height;
setMeasuredDimension(imageSize, imageSize);
}
private int measureWidth(int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = specSize;
}
return result;
}
private int measureHeight(int measureSpecHeight) {
int result;
int specMode = MeasureSpec.getMode(measureSpecHeight);
int specSize = MeasureSpec.getSize(measureSpecHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = specSize;
}
return (result + 2);
}
public void setWaveBgColor(int color) {
this.mWaveBgColor = color;
mWaveBgPaint.setColor(this.mWaveBgColor);
updateWaveShader();
invalidate();
}
public int getWaveBgColor() {
return mWaveBgColor;
}
public void setWaveColor(int color) {
mWaveColor = color;
updateWaveShader();
invalidate();
}
public int getWaveColor() {
return mWaveColor;
}
public void setBorderWidth(float width) {
mBorderPaint.setStrokeWidth(width);
invalidate();
}
public float getBorderWidth() {
return mBorderPaint.getStrokeWidth();
}
public void setBorderColor(int color) {
mBorderPaint.setColor(color);
updateWaveShader();
invalidate();
}
public int getBorderColor() {
return mBorderPaint.getColor();
}
public void setAmplitudeRatio(int amplitudeRatio) {
if (this.mAmplitudeRatio != (float) amplitudeRatio / 1000) {
this.mAmplitudeRatio = (float) amplitudeRatio / 1000;
invalidate();
}
}
public float getAmplitudeRatio() {
return mAmplitudeRatio;
}
public int getProgressValue() {
return mProgressValue;
}
public void setWaveShiftRatio(float waveShiftRatio) {
if (this.mWaveShiftRatio != waveShiftRatio) {
this.mWaveShiftRatio = waveShiftRatio;
invalidate();
}
}
public float getWaveShiftRatio() {
return mWaveShiftRatio;
}
public void setWaterLevelRatio(float waterLevelRatio) {
if (this.mWaterLevelRatio != waterLevelRatio) {
this.mWaterLevelRatio = waterLevelRatio;
invalidate();
}
}
public float getWaterLevelRatio() {
return mWaterLevelRatio;
}
public void startAnimation() {
if (mAnimatorSet != null) {
mAnimatorSet.start();
}
}
public void endAnimation() {
if (mAnimatorSet != null) {
mAnimatorSet.end();
}
}
public void cancelAnimation() {
if (mAnimatorSet != null) {
mAnimatorSet.cancel();
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@SuppressWarnings("deprecation")
public void pauseAnimation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (mAnimatorSet != null) {
mAnimatorSet.pause();
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@SuppressWarnings("deprecation")
public void resumeAnimation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (mAnimatorSet != null) {
mAnimatorSet.resume();
}
}
}
public void setAnimDuration(long duration) {
waveShiftAnim.setDuration(duration);
}
@Override
protected void onAttachedToWindow() {
startAnimation();
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
cancelAnimation();
super.onDetachedFromWindow();
}
private int adjustAlpha(int color, float factor) {
int alpha = Math.round(Color.alpha(color) * factor);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}
private int dp2px(float dp) {
final float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
}
attrs
xml
android:id="@+id/sixWave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:sw_borderColor="@color/colorAccent"
app:sw_borderWidth="3dp"
app:sw_progressValue="70"
app:sw_waveAmplitude="50"
app:sw_waveColor="@color/colorAccent" />
activity
override fun initData() {
// sixWave.setBorderColor(Color.BLUE)
// sixWave.setWaveColor(Color.BLUE)
// sixWave.setWaveBgColor(Color.TRANSPARENT)
// sixWave.setAmplitudeRatio(40)
// sixWave.setWaveShiftRatio(0.2f)
// sixWave.setProgressValue(70)
sixWave.setAnimDuration(3000)
}
六边形图形效果根据WaveLoadingView修改。可以改多种样式,三角形,正方形,矩形,圆形,圆角矩形
android 六边形简书,水波浪贝塞尔效果(六边形)相关推荐
- android计步器简书,自定义View-仿QQ运动步数进度效果
自定义View-仿QQ运动步数进度效果 一.写在前面 (1) 图一,仿QQ步数运行效果 (2) 图二,完整的圆效果 完整代码请看这 二.正文开始 (1)首先来个三部曲,自定义属性,布局设置,属性获取 ...
- android 仿简书评论,Android仿简书搜索框效果的示例代码
前言 之前用简书的时候一直是在web端,后来下载了客户端,看到了搜索的那个动画,就尝试的去写了,没写之前感觉挺容易的,写了之后,就感觉里面还是有些要注意的东西的.话不多说,直接上图. Activity ...
- Android仿简书、淘宝等APP View弹出效果
在用简书App的时候觉得这个View的弹出效果特别好,而且非常平滑. 先看看效果: 主要是scale,alpha,translation几个普通动画组合,这里不再分析. 实现效果图: 代码:https ...
- android 六边形简书,深入理解六边形架构
六边形架构或六角架构是Alistair Cockburn在2005年提出,解决了传统的分层架构所带来的问题,实际上它也是一种分层架构,只不过不是上下或左右,而是变成了内部和外部.在领域驱动设计(DDD ...
- 实现简书个人中心UI效果
这两天比较闲,简单实现了一下个人中心页面scrollView嵌套的效果,也就是下边这个页面,大家感受一下先: JSDemo2.gif 首先讲下实现思路,很多人看到这个界面觉得是多个scrollView ...
- android jsoup简书,jsoup爬虫简书首页数据做个小Demo
昨天LZ去面试,遇到一个大牛,被血虐一番,发现自己基础还是很薄弱,对java一些原理掌握的还是不够稳固,比如java反射注解,知道一点就是说不出来,很尴尬... 生命不止,学习不止啊 之前那个项目 Q ...
- android 仿简书评论,Android 开发仿简书登录框可删除内容或显示密码框的内容
简书App 是我很喜欢的一款软件.今天就模仿了一下他的登录框.先上图: 好了下面上代码,自定义ImgEditText 继承与EditText.重写一些方法. package lyf.myimgedit ...
- android仿简书编辑器,类似zine,简书的app移动编辑器-Light Seven
原标题:类似zine,简书的app移动编辑器-Light Seven 无论你是否从事文字编辑工作,我相信每个人都会接触到文字编辑.既然接触到文字编辑,顺理成章的就会接触到文字编辑的应用和软件. 在生活 ...
- android 购物车 简书,Android仿饿了么购物车效果
先看下效果图: ezgif-1-8f133ca916.gif 1.首先列表布局采用Recycleview android:id="@+id/container" android:l ...
- android 心跳 简书,如何高效维持网络长连接:手把手教你实现 自适应的心跳保活机制...
前言 当实现具备实时性需求时,我们一般会选择长连接的通信方式 而在实现长连接方式时,存在很多性能问题,如 长连接保活 今天,我将 手把手教大家实现自适应的心跳保活机制,从而能高效维持长连接 目录 示意 ...
最新文章
- 链表问题11——两个单链表相交的系列问题(三):判断两个有环链表是否相交
- BZOJ2741 【FOTILE模拟赛】L
- java RSA加密解密实现(含分段加密)
- java获取项目的部署目录结构_JAVA WEB项目目录结构以及web应用部署的根目录,编译路径和项目根目录的区别...
- 我的技术回顾因ABP框架触发DevOps云原生之路-2020年
- Python爬虫用Selenium抓取js生成的文件(一)
- vue设置img大小的属性_Vue.js自定义标签属性并获取属性,及绑定img的src属性的坑...
- [Python] L1-021. 重要的话说三遍-PAT团体程序设计天梯赛GPLT
- hdfs 中chunk_HDFS读写流程
- CUDA安装失败,及解决方案
- [PKUSC2018游记]
- JAVA面试技巧之项目介绍
- Android APP如何获取framework下的资源?
- STM32L476入坑-3-新建工程并点亮LED灯
- 解决margin坍塌
- 高校青年教师应该怎么提高收入
- windows 多开微信
- 关于计算机系调查问卷表,计算机系统调查问卷.xls
- 关于sdcard读写速率慢的问题排查
- 麒麟系统(Fedora 64)安装谷歌(chrome)浏览器