上实现效果
3.gif
这个效果是通过两个布局,分别都有动画效果来进行实现的
public class PowerCoolLayout extends View {
private Paint paint;
private Bitmap bitmap;
private int dp250;
private int dp100;
private Rect rect;
private LinearGradient greenShader;
private LinearGradient redShader;
private Paint gradientPaint;
private ValueAnimator valueAnimator;
private Path snowPath;
private Path snowPath2;
private Path snowPath3;
private PathMeasure pathMeasure;
private PathMeasure pathMeasure2;
private PathMeasure pathMeasure3;
private float[] mCurrentPosition = new float[2];
private float[] mCurrentPosition2 = new float[2];
private float[] mCurrentPosition3 = new float[2];
private Bitmap snowBitmap;
private Bitmap snowBitmap2;
private Rect bitmapRect2;
private Rect desBitmapRect2;
private Rect bitmapRect3;
private Rect desBitmapRect3;
//摄氏度的值
private String drawCelsiusText;
private double currentCelsius;
public PowerCoolLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(UiUtils.dp2px(getContext(), 40));
gradientPaint = new Paint();
bitmap = getBitmap(R.drawable.ic_report_mobile_cool, false);
dp250 = UiUtils.dp2px(getContext(), 150);
dp100 = UiUtils.dp2px(getContext(), 100);
snowPath = new Path();
snowPath2 = new Path();
snowPath3 = new Path();
snowBitmap = getBitmap(R.drawable.ic_snow, false);
snowBitmap2 = getBitmap(R.drawable.ic_snow, true);
drawCelsiusText = String.valueOf(MyApplication.PHONE_CELSIUS) + "°";
currentCelsius = getRandomCool();
}
/**
* 来回降5度多一点
*
* @return
*/
private double getRandomCool() {
return (((int) (new Random().nextDouble() * 100)) / 100.0 + 9);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (valueAnimator == null) {
bitmapRect2 = new Rect(0, 0, snowBitmap.getWidth(), snowBitmap.getHeight());
desBitmapRect2 = new Rect(0, 0, snowBitmap.getWidth() / 2, snowBitmap.getHeight() / 2);
bitmapRect3 = new Rect();
desBitmapRect3 = new Rect();
handlePathMeasure();
rect = new Rect(0, 0, getWidth(), getHeight());
greenShader = new LinearGradient(0, 0, getWidth(), getHeight(), new int[]{getResources().getColor(R.color.c_0043ff), getResources().getColor(R.color.c_008dff)}, null, Shader.TileMode.REPEAT);
redShader = new LinearGradient(0, 0, getWidth(), getHeight(), new int[]{getResources().getColor(R.color.c_FF6A00), getResources().getColor(R.color.c_F49F1F)}, null, Shader.TileMode.REPEAT);
gradientPaint.setShader(redShader);
}
}
private void handlePathMeasure() {
int centerX = (int) (getWidth() / 2.0);
int centerY = (int) (dp250 + bitmap.getHeight() / 2.0f);
snowPath.moveTo(0, 0);
snowPath.lineTo(centerX, centerY);
pathMeasure = new PathMeasure(snowPath, false);
snowPath2.moveTo(getWidth(), 0);
snowPath2.lineTo(centerX, centerY);
pathMeasure2 = new PathMeasure(snowPath2, false);
snowPath3.moveTo(getWidth(), getHeight() - dp250);
snowPath3.lineTo(centerX, centerY);
pathMeasure3 = new PathMeasure(snowPath3, false);
initValueAnim(1, pathMeasure);
initValueAnim(2, pathMeasure2);
initValueAnim(3, pathMeasure3);
}
private void initValueAnim(int type, PathMeasure pathMeasure) {
float length = pathMeasure.getLength();
valueAnimator = ValueAnimator.ofFloat(0, length);
valueAnimator.addUpdateListener(animation -> {
float animatedValue = (float) animation.getAnimatedValue();
//mCurrentPosition 传进去,就被复制了
if (type == 1) {
pathMeasure.getPosTan(animatedValue, mCurrentPosition, null);
} else if (type == 2) {
pathMeasure.getPosTan(animatedValue, mCurrentPosition2, null);
} else {
pathMeasure.getPosTan(animatedValue, mCurrentPosition3, null);
}
onPercent(animatedValue / length);
invalidate();
});
valueAnimator.setDuration(3000);
valueAnimator.start();
}
private void onPercent(float percent) {
drawCelsiusText = getLastDoubleValue(MyApplication.PHONE_CELSIUS - ((currentCelsius) * percent)) + "°";
if (percent > 0.6f) {
gradientPaint.setShader(greenShader);
}
if (coolChangeListener != null) {
coolChangeListener.onChangePercent(percent);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(snowPath, paint);
canvas.drawRect(rect, gradientPaint);
canvas.drawBitmap(bitmap, (getWidth() - bitmap.getWidth()) / 2.0f, dp250, paint);
// String text = "35.1°";
//画摄氏度的变化
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(drawCelsiusText, (getWidth()) / 2.0f, dp250 + dp100 + bitmap.getHeight(), paint);
canvas.drawBitmap(snowBitmap, mCurrentPosition[0], mCurrentPosition[1], paint);
canvas.drawBitmap(snowBitmap2, mCurrentPosition2[0], mCurrentPosition2[1], paint);
canvas.drawBitmap(snowBitmap2, mCurrentPosition3[0], mCurrentPosition3[1], paint);
}
private Bitmap getBitmap(int drawableRes, boolean isHalf) {
Drawable drawable = getResources().getDrawable(drawableRes);
return drawableToBitmap(drawable, isHalf);
}
/**
* Drawable转换成一个Bitmap
*
* @param drawable drawable对象
* @return
*/
private Bitmap drawableToBitmap(Drawable drawable, boolean isHalf) {
Bitmap bitmap = null;
if (isHalf) {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth() / 2, drawable.getIntrinsicHeight() / 2,
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
}
Canvas canvas = new Canvas(bitmap);
if (isHalf) {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth() / 2, drawable.getIntrinsicHeight() / 2);
} else {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
}
drawable.draw(canvas);
return bitmap;
}
private double getLastDoubleValue(double value) {
return ((int) (value * 10)) / 10.0;
}
private PowerCoolChangeListener coolChangeListener;
public void setCoolChangeListener(PowerCoolChangeListener coolChangeListener) {
this.coolChangeListener = coolChangeListener;
}
public interface PowerCoolChangeListener {
void onChangePercent(float percent);
}
}
PowerCoolLayout是进来的时候的,然后带了个界面,电路板界面的动画效果,中间的个电路板是图片
然后通过canvas.drawText来进行温度的绘制,变化是通过动画来进行变化的
public class GoodChangeLayout extends LinearLayout {
private ValueAnimator valueAnimator;
private int currentHeight;
private TextView tvDec;
public GoodChangeLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setGravity(Gravity.CENTER);
setOrientation(VERTICAL);
View.inflate(getContext(), R.layout.view_good_change_layout, this);
tvDec = findViewById(R.id.tvDec);
// currentHeight = (getResources().getDisplayMetrics().heightPixels * 2) / 3;
currentHeight = UiUtils.dp2px(getContext(), 1080);
valueAnimator = ValueAnimator.ofInt(currentHeight, UiUtils.dp2px(getContext(), 220));
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(animation -> {
int animatedValue = (int) animation.getAnimatedValue();
// layout(0, 0, getWidth(), animatedValue);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
layoutParams.height = animatedValue;
setLayoutParams(layoutParams);
});
}
// @Override
// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, currentHeight);
// }
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// if (gradientPaint == null) {
// gradientPaint = new Paint();
// greenShader = new LinearGradient(0, 0, getWidth(), currentHeight, new int[]{getResources().getColor(R.color.c_0043ff), getResources().getColor(R.color.c_008dff)}, null, Shader.TileMode.REPEAT);
// rect = new Rect(0, 0, getWidth(), currentHeight);
// gradientPaint.setShader(greenShader);
//
// }
}
public void setTvDec(String value) {
tvDec.setText(value);
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawRect(rect, gradientPaint);
super.onDraw(canvas);
}
public void startAnim() {
if (valueAnimator.isRunning()) {
return;
}
if (valueAnimator != null) {
valueAnimator.start();
}
}
}
GoodChangeLayout 就是最后显示成功的那个界面,这个界面通过动画改边自己的高度来实现动画,一开始想使用layout来进行实现,发现出现了点问题,只是把本地布局进行了修改
这里记录一下layout,layout的具体是什么意思
public class PowerCoolActivity extends BaseAppCompatActivity {
public static final String TAG = "PowerCoolActivity";
private PowerCoolLayout pclLayout;
private GoodChangeLayout gclLayout;
private Toolbar mToolBar;
public static void start(Context context) {
Intent intent = new Intent(context, PowerCoolActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
// Translucent status bar
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
setContentView(R.layout.activity_power_cool);
initToolBar();
initOtherIds();
}
private void initOtherIds() {
gclLayout = findViewById(R.id.gclLayout);
pclLayout = findViewById(R.id.pclLayout);
pclLayout.setCoolChangeListener(percent -> {
if (percent == 1) {
pclLayout.setVisibility(View.GONE);
gclLayout.startAnim();
}
});
}
private void initToolBar() {
mToolBar = findViewById(R.id.toolBar);
mToolBar.setTitle("");
mToolBar.setTitleTextColor(getResources().getColor(R.color.white));
mToolBar.setNavigationIcon(R.drawable.white_return);
setSupportActionBar(mToolBar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onSupportNavigateUp() {
finish();
return super.onSupportNavigateUp();
}
}
PowerCoolActivity实际是一个展示的载体
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/clear_blue_selector"
tools:context=".ui.clear.PowerCoolActivity">
<android.support.v4.widget.NestedScrollView
android:id="@+id/nsvScroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.mobi.clearsafe.ui.clear.widget.GoodChangeLayout
android:id="@+id/gclLayout"
android:layout_width="match_parent"
android:layout_height="1080dp" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/white_cron18_selector"
android:padding="18dp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<com.mobi.clearsafe.ui.clear.widget.PowerCoolLayout
android:id="@+id/pclLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:fitsSystemWindows="true"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
PowerCoolActivity对应的xml