我一直在使用位图在View中渲染小的彩色圆圈。现在,我想在点击时在这些圆圈周围显示自定义的涟漪动画。
搜索了StackOverflow的答案一段时间后,通常建议将这些位图包装在VIEW中,然后使用Android的动画框架将Animations应用于这些视图。
但是问题是,我已经通过
使用该视图的画布在视图内绘制了这些位图 canvas.drawBitmap()
功能。我只想显示单击时围绕这些位图的波纹。我的问题是,是否可以在不将其包装为视图的情况下向位图提供波纹或任何动画?
protected void fill(ILineDataSet set, boolean drawCircleHole,
boolean drawTransparentCircleHole, int selectedEntryIndex) {
int colorCount = set.getCircleColorCount();
int holeColorCount = set.getCircleHoleColorCount();
circleRadius = set.getCircleRadius();
circleHoleRadius = set.getCircleHoleRadius();
for (int i = 0; i < (colorCount > holeColorCount ? colorCount: holeColorCount); i++) {
Bitmap.Config conf = Bitmap.Config.ARGB_4444;
Bitmap circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1),
(int) (circleRadius * 2.1), conf);
Canvas canvas = new Canvas(circleBitmap);
circleBitmaps[i] = circleBitmap;
//fill colors in the values' circles
mRenderPaint.setColor(set.getCircleColor(i < colorCount ? i : 0));
mCirclePaintInner.setColor(set.getCircleHoleColor(i < holeColorCount ? i : 0));
if (drawTransparentCircleHole) {
// Begin path for circle with hole
mCirclePathBuffer.reset();
mCirclePathBuffer.addCircle(
circleRadius,
circleRadius,
circleRadius,
Path.Direction.CW);
// Cut hole in path
mCirclePathBuffer.addCircle(
circleRadius,
circleRadius,
circleHoleRadius,
Path.Direction.CCW);
// Fill in-between
canvas.drawPath(mCirclePathBuffer, mRenderPaint);
} else {
canvas.drawCircle(
circleRadius,
circleRadius,
circleRadius,
mRenderPaint);
if (drawCircleHole) {
canvas.drawCircle(
circleRadius,
circleRadius,
circleHoleRadius,
mCirclePaintInner);
}
}
if (i == selectedEntryIndex) {
circleBitmaps[i] = getScaledUpBitmap(circleBitmaps[i]);
}
}
}
private Bitmap getScaledUpBitmap(Bitmap bm) {
//scale bitmap as twice its size
int width = bm.getWidth();
int height = bm.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(1.5f, 1.5f);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
答案 0 :(得分:0)
Android Ripple动画是不断增长的动画+淡入淡出动画的组合。 换句话说,这是一个绘制过程,因此不建议直接在位图上进行绘制。
我写了一个类,它是可以用作触摸面板的布局。
此布局称为RippleLayout
,是从RelativeLayout
扩展而来的。您可以使用此布局绘制圆并管理onTouchListener
事件以在给定点上显示波纹动画。
RippleLayout.java
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
public class RippleLayout extends RelativeLayout {
private AnimatorSet mAnimatorSet;
private Paint mPaint;
private boolean mStarted;
private float mX, mY;
private int mCount = 1;
private int mDuration = 300;
private float mRadius = 300;
private IntRippleView rippleView;
public RippleLayout(Context context) {
this(context, null, 0);
}
public RippleLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RippleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void build() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.GRAY);
List<Animator> animators = new ArrayList<>();
rippleView = new IntRippleView(getContext());
rippleView.setCircleRadius(0);
rippleView.setCircleAlpha(1);
addView(rippleView);
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleView, "CircleRadius", 0f, 1f);
scaleXAnimator.setRepeatCount(0);
animators.add(scaleXAnimator);
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleView, "CircleAlpha", 1f, 0f);
alphaAnimator.setRepeatCount(0);
animators.add(alphaAnimator);
mAnimatorSet = new AnimatorSet();
mAnimatorSet.setInterpolator(new LinearInterpolator());
mAnimatorSet.playTogether(animators);
mAnimatorSet.setDuration(mDuration);
mAnimatorSet.addListener(mAnimatorListener);
}
public void doRipple(float x, float y) {
doRipple(x, y, mRadius, mPaint.getColor());
}
public synchronized void doRipple(float x, float y, float radius, int acolor) {
if (mStarted)
mAnimatorSet.end();
mX = x;
mY = y;
mRadius = radius;
rippleView.bringToFront();
mPaint.setColor(acolor);
mAnimatorSet.start();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
build();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAnimatorSet != null) {
mAnimatorSet.cancel();
mAnimatorSet = null;
}
mPaint = null;
}
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
mStarted = true;
}
@Override
public void onAnimationEnd(Animator animator) {
mStarted = false;
}
@Override
public void onAnimationCancel(Animator animator) {
mStarted = false;
}
@Override
public void onAnimationRepeat(Animator animator) {
}
};
private class IntRippleView extends View {
public IntRippleView(Context context) {
super(context);
}
private float CircleRadius = 0;
public void setCircleRadius(float value) {
CircleRadius = value;
invalidate();
}
public float getCircleRadius() {
return CircleRadius;
}
private float CircleAlpha = 1;
public void setCircleAlpha(float value) {
CircleAlpha = value;
invalidate();
}
public float getCircleAlpha() {
return CircleAlpha;
}
@Override
protected void onDraw(Canvas canvas) {
int aColor = Color.RED;
mPaint.setAlpha((int)(255 * CircleAlpha));
canvas.drawCircle(mX, mY, mRadius * CircleRadius, mPaint);
}
}
}
使用方法
在XML布局中
<android.support.constraint.ConstraintLayout
android:id="@+id/mainlayout"
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:padding="0dp"
>
<com.mcblau.pacerblue.components.RippleLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
>
</com.mcblau.pacerblue.components.RippleLayout>
</android.support.constraint.ConstraintLayout>
在您的活动中
container = findViewById(R.id.container);
container.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// detect here which circle was touch
// get the center of the circle => mCenterX, mCenterY
container.doRipple(mCenterX, mCenterY); // ripple animation
return true;
}
});
您可以在RippleLayout上或在另一个平面上直接绘制圆。如果将RippleLayout
恰好放在位图布局上,则可以将其用作触摸面板。在这种情况下,请使用圈子布局的setOnTouchListener
。
使用doRipple(x, y);
或doRipple(x, y, radius, acolor);
设置圆半径为波纹颜色。