Android实现仪表盘效果

本文实例为大家分享了Android实现仪表盘效果的具体代码,供大家参考,具体内容如下

仪表盘效果,圆弧可变色,效果图如下:

通过自定义view实现,代码如下:

public class DashboardView extends View {
    private int mRadius; // 画布边缘半径(去除padding后的半径)
    private int mStartAngle = 150; // 起始角度
    private int mSweepAngle = 240; // 绘制角度
    private int mMin = 1; // 最小值
    private int mMax = 8; // 最大值
    private int mSection = 8; // 值域(mMax-mMin)等分份数
    private int mPortion = 3; // 一个mSection等分份数
    private String mHeaderText = ""; // 表头
    private int mCreditValue = (int) 8.12; // 信用分
    private int mSolidCreditValue = mCreditValue; // 信用分(设定后不变)
    private int mSparkleWidth; // 亮点宽度
    private int mProgressWidth; // 进度圆弧宽度
    private float mLength1; // 刻度顶部相对边缘的长度
    private int mCalibrationWidth; // 刻度圆弧宽度
    private float mLength2; // 刻度读数顶部相对边缘的长度

    private int mPadding;
    private float mCenterX, mCenterY; // 圆心坐标
    private Paint mPaint;
    private RectF mRectFProgressArc;
    private RectF mRectFCalibrationFArc;
    private RectF mRectFTextArc;
    private Path mPath;
    private Rect mRectText;
    private String[] mTexts;
    private int mBackgroundColor;
    private int[] mBgColors;

    private boolean isAnimFinish = true;
    private float mAngleWhenAnim;

    public DashboardView(Context context) {
        this(context, null);
    }

    public DashboardView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    private void init() {
        mSparkleWidth = dp2px(10);
        mProgressWidth = dp2px(3);
        mCalibrationWidth = dp2px(10);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        mRectFProgressArc = new RectF();
        mRectFCalibrationFArc = new RectF();
        mRectFTextArc = new RectF();
        mPath = new Path();
        mRectText = new Rect();

        mTexts = new String[]{"", "Ⅳ", "", "Ⅲ", "", "Ⅱ", "", "Ⅰ", ""};
        mBgColors = new int[]{ContextCompat.getColor(getContext(), R.color.color_red),
                ContextCompat.getColor(getContext(), R.color.color_orange),
                ContextCompat.getColor(getContext(), R.color.color_yellow),
                ContextCompat.getColor(getContext(), R.color.color_green),
                ContextCompat.getColor(getContext(), R.color.color_blue)};
        mBackgroundColor = mBgColors[0];
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mPadding = Math.max(
                Math.max(getPaddingLeft(), getPaddingTop()),
                Math.max(getPaddingRight(), getPaddingBottom())
        );
        setPadding(mPadding, mPadding, mPadding, mPadding);

        mLength1 = mPadding + mSparkleWidth / 2f + dp2px(8);
        mLength2 = mLength1 + mCalibrationWidth + dp2px(1) + dp2px(5);

        int width = resolveSize(dp2px(220), widthMeasureSpec);
        mRadius = (width - mPadding * 2) / 2;

        setMeasuredDimension(width, width - dp2px(30));

        mCenterX = mCenterY = getMeasuredWidth() / 2f;
        mRectFProgressArc.set(
                mPadding + mSparkleWidth / 2f,
                mPadding + mSparkleWidth / 2f,
                getMeasuredWidth() - mPadding - mSparkleWidth / 2f,
                getMeasuredWidth() - mPadding - mSparkleWidth / 2f
        );

        mRectFCalibrationFArc.set(
                mLength1 + mCalibrationWidth / 2f,
                mLength1 + mCalibrationWidth / 2f,
                getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f,
                getMeasuredWidth() - mLength1 - mCalibrationWidth / 2f
        );

        mPaint.setTextSize(sp2px(10));
        mPaint.getTextBounds("0", 0, "0".length(), mRectText);
        mRectFTextArc.set(
                mLength2 + mRectText.height(),
                mLength2 + mRectText.height(),
                getMeasuredWidth() - mLength2 - mRectText.height(),
                getMeasuredWidth() - mLength2 - mRectText.height()
        );
    }

    @SuppressLint("ResourceAsColor")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        canvas.drawColor(mBackgroundColor);
//        canvas.drawColor(R.color.color_blue);

        /**
         * 画进度圆弧背景
         */
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mProgressWidth);
        mPaint.setAlpha(80);
        mPaint.setColor(mBackgroundColor);
        canvas.drawArc(mRectFProgressArc, mStartAngle + 1, mSweepAngle - 2, false, mPaint);

        mPaint.setAlpha(255);
        if (isAnimFinish) {
            /**
             * 画进度圆弧(起始到信用值)
             */
            mPaint.setShader(generateSweepGradient());
            mPaint.setColor(mBackgroundColor);
            canvas.drawArc(mRectFProgressArc, mStartAngle + 1,
                    calculateRelativeAngleWithValue(mCreditValue) - 2, false, mPaint);
            /**
             * 画指示亮点
             */
            float[] point = getCoordinatePoint(
                    mRadius - mSparkleWidth / 2f,
                    mStartAngle + calculateRelativeAngleWithValue(mCreditValue)
            );
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setShader(generateRadialGradient(point[0], point[1]));
            mPaint.setColor(mBackgroundColor);
            canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);
        } else {
            /**
             * 画进度圆弧(起始到信用值)
             */
            mPaint.setShader(generateSweepGradient());
            mPaint.setColor(mBackgroundColor);
            canvas.drawArc(mRectFProgressArc, mStartAngle + 1,
                    mAngleWhenAnim - mStartAngle - 2, false, mPaint);
            /**
             * 画指示亮点
             */
            float[] point = getCoordinatePoint(
                    mRadius - mSparkleWidth / 2f,
                    mAngleWhenAnim
            );
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(mBackgroundColor);
            mPaint.setShader(generateRadialGradient(point[0], point[1]));
            canvas.drawCircle(point[0], point[1], mSparkleWidth / 2f, mPaint);
        }

        /**
         * 画刻度圆弧
         */
        mPaint.setShader(null);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.WHITE);
        mPaint.setAlpha(80);
        mPaint.setStrokeCap(Paint.Cap.SQUARE);
        mPaint.setStrokeWidth(mCalibrationWidth);
        mPaint.setColor(mBackgroundColor);
        canvas.drawArc(mRectFCalibrationFArc, mStartAngle + 3, mSweepAngle - 6, false, mPaint);

        /**
         * 画长刻度
         * 画好起始角度的一条刻度后通过canvas绕着原点旋转来画剩下的长刻度
         */
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(dp2px(2));
        mPaint.setAlpha(120);
        mPaint.setColor(mBackgroundColor);
        float x0 = mCenterX;
        float y0 = mPadding + mLength1 + dp2px(1);
        float x1 = mCenterX;
        float y1 = y0 + mCalibrationWidth;
        // 逆时针到开始处
        canvas.save();
        canvas.drawLine(x0, y0, x1, y1, mPaint);
        float degree = mSweepAngle / mSection;
        for (int i = 0; i < mSection / 2; i++) {
            canvas.rotate(-degree, mCenterX, mCenterY);
            canvas.drawLine(x0, y0, x1, y1, mPaint);
        }
        canvas.restore();
        // 顺时针到结尾处
        canvas.save();
        for (int i = 0; i < mSection / 2; i++) {
            canvas.rotate(degree, mCenterX, mCenterY);
            canvas.drawLine(x0, y0, x1, y1, mPaint);
        }
        canvas.restore();

        /**
         * 画短刻度
         * 同样采用canvas的旋转原理
         */
        mPaint.setStrokeWidth(dp2px(1));
        mPaint.setAlpha(80);
        mPaint.setColor(mBackgroundColor);
        float x2 = mCenterX;
        float y2 = y0 + mCalibrationWidth - dp2px(2);
        // 逆时针到开始处
        canvas.save();
        canvas.drawLine(x0, y0, x2, y2, mPaint);
        degree = mSweepAngle / (mSection * mPortion);
        for (int i = 0; i < (mSection * mPortion) / 2; i++) {
            canvas.rotate(-degree, mCenterX, mCenterY);
            canvas.drawLine(x0, y0, x2, y2, mPaint);
        }
        canvas.restore();
        // 顺时针到结尾处
        canvas.save();
        for (int i = 0; i < (mSection * mPortion) / 2; i++) {
            canvas.rotate(degree, mCenterX, mCenterY);
            canvas.drawLine(x0, y0, x2, y2, mPaint);
        }
        canvas.restore();

        /**
         * 画长刻度读数
         * 添加一个圆弧path,文字沿着path绘制
         */
        mPaint.setTextSize(sp2px(10));
        mPaint.setTextAlign(Paint.Align.LEFT);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAlpha(160);
        mPaint.setColor(mBackgroundColor);
        for (int i = 0; i < mTexts.length; i++) {
            mPaint.getTextBounds(mTexts[i], 0, mTexts[i].length(), mRectText);
            // 粗略把文字的宽度视为圆心角2*θ对应的弧长,利用弧长公式得到θ,下面用于修正角度
            float θ = (float) (180 * mRectText.width() / 2 /
                    (Math.PI * (mRadius - mLength2 - mRectText.height())));

            mPath.reset();
            mPath.addArc(
                    mRectFTextArc,
                    mStartAngle + i * (mSweepAngle / mSection) - θ, // 正起始角度减去θ使文字居中对准长刻度
                    mSweepAngle
            );
            canvas.drawTextOnPath(mTexts[i], mPath, 0, 0, mPaint);
        }

        /**
         * 画实时度数值
         */
        mPaint.setAlpha(255);
        mPaint.setTextSize(sp2px(50));
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(mBackgroundColor);
//        String value = String.valueOf(mSolidCreditValue);
        String value = "";
        if (mSolidCreditValue > 6) {
            //"Ⅳ", "", "Ⅲ", "", "Ⅱ", "", "Ⅰ",
            value = "Ⅰ";
        } else if (5 < mSolidCreditValue && mSolidCreditValue <= 6) {
            value = "Ⅱ";
        } else if (4 < mSolidCreditValue && mSolidCreditValue <= 5) {
            value = "Ⅲ";
        } else if (3 < mSolidCreditValue && mSolidCreditValue <= 4) {
            value = "Ⅳ";
        }
        canvas.drawText(value, mCenterX, mCenterY + dp2px(30), mPaint);

        /**
         * 画表头
         */
        mPaint.setAlpha(160);
        mPaint.setTextSize(sp2px(12));
        mPaint.setColor(Color.BLACK);
        canvas.drawText(mHeaderText, mCenterX, mCenterY - dp2px(20), mPaint);

        /**
         * 画描述
         */
        mPaint.setAlpha(255);
        mPaint.setTextSize(sp2px(20));
        mPaint.setColor(mBackgroundColor);
        canvas.drawText(calculateCreditDescription(), mCenterX, mCenterY + dp2px(55), mPaint);

        /**
         * 画评估时间
         */
        mPaint.setAlpha(160);
        mPaint.setTextSize(sp2px(10));
        mPaint.setColor(Color.BLACK);
        canvas.drawText(getFormatTimeStr(), mCenterX, mCenterY + dp2px(70), mPaint);
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                Resources.getSystem().getDisplayMetrics());
    }

    private SweepGradient generateSweepGradient() {
        SweepGradient sweepGradient = new SweepGradient(mCenterX, mCenterY,
                new int[]{Color.argb(0, 255, 255, 255), Color.argb(200, 255, 255, 255)},
                new float[]{0, calculateRelativeAngleWithValue(mCreditValue) / 360}
        );
        Matrix matrix = new Matrix();
        matrix.setRotate(mStartAngle - 1, mCenterX, mCenterY);
        sweepGradient.setLocalMatrix(matrix);

        return sweepGradient;
    }

    private RadialGradient generateRadialGradient(float x, float y) {
        return new RadialGradient(x, y, mSparkleWidth / 2f,
                new int[]{Color.argb(255, 255, 255, 255), Color.argb(80, 255, 255, 255)},
                new float[]{0.4f, 1},
                Shader.TileMode.CLAMP
        );
    }

    private float[] getCoordinatePoint(float radius, float angle) {
        float[] point = new float[2];

        double arcAngle = Math.toRadians(angle); //将角度转换为弧度
        if (angle < 90) {
            point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
        } else if (angle == 90) {
            point[0] = mCenterX;
            point[1] = mCenterY + radius;
        } else if (angle > 90 && angle < 180) {
            arcAngle = Math.PI * (180 - angle) / 180.0;
            point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
        } else if (angle == 180) {
            point[0] = mCenterX - radius;
            point[1] = mCenterY;
        } else if (angle > 180 && angle < 270) {
            arcAngle = Math.PI * (angle - 180) / 180.0;
            point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
        } else if (angle == 270) {
            point[0] = mCenterX;
            point[1] = mCenterY - radius;
        } else {
            arcAngle = Math.PI * (360 - angle) / 180.0;
            point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
            point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
        }

        return point;
    }

    /**
     * 相对起始角度计算所对应的角度大小
     */
    private float calculateRelativeAngleWithValue(int value) {
        float degreePerSection = 1f * mSweepAngle / mSection;
        if (value > 6) {
            return 8 * degreePerSection + 2 * degreePerSection / 250 * (value - 6);
        } else if (value > 5) {
            return 6 * degreePerSection + 2 * degreePerSection / 50 * (value - 5);
        } else if (value > 4) {
            return 4 * degreePerSection + 2 * degreePerSection / 50 * (value - 4);
        } else if (value > 3) {
            return 2 * degreePerSection + 2 * degreePerSection / 50 * (value - 3);
        } else {
            return 2 * degreePerSection / 200 * (value - 1);
        }
    }

    /**
     * 信用分对应描述
     */
    private String calculateCreditDescription() {
        if (mSolidCreditValue > 6) {
            return "";
        } else if (mSolidCreditValue > 5) {
            return "";
        } else if (mSolidCreditValue > 4) {
            return "";
        } else if (mSolidCreditValue > 3) {
            return "";
        }
        return "";
    }

    private SimpleDateFormat mDateFormat;

    private String getFormatTimeStr() {
        if (mDateFormat == null) {
            mDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm", Locale.CHINA);
        }
        return String.format("", mDateFormat.format(new Date()));
//        return String.format("监测日期:%s", "2020-05-04");
    }

    public int getCreditValue() {
        return mCreditValue;
    }

    /**
     * 设置值
     *
     * @param creditValue
     */
    public void setCreditValue(int creditValue) {
        if (mSolidCreditValue == creditValue || creditValue < mMin || creditValue > mMax) {
            return;
        }

        mSolidCreditValue = creditValue;
        mCreditValue = creditValue;
        postInvalidate();
    }

    /**
     * 设置并播放动画
     *
     * @param creditValue 值
     */
    public void setCreditValueWithAnim(int creditValue) {
        if (creditValue < mMin || creditValue > mMax || !isAnimFinish) {
            return;
        }

        mSolidCreditValue = creditValue;

        ValueAnimator creditValueAnimator = ValueAnimator.ofInt(1, mSolidCreditValue);
        creditValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mCreditValue = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });

        // 计算最终值对应的角度,以扫过的角度的线性变化来播放动画
        float degree = calculateRelativeAngleWithValue(mSolidCreditValue);

        ValueAnimator degreeValueAnimator = ValueAnimator.ofFloat(mStartAngle, mStartAngle + degree);
        degreeValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mAngleWhenAnim = (float) animation.getAnimatedValue();
            }
        });

        @SuppressLint("ObjectAnimatorBinding") ObjectAnimator colorAnimator = ObjectAnimator.ofInt(this, "mBackgroundColor", mBgColors[0], mBgColors[0]);
        // 实时信用值对应的背景色的变化
        long delay = 1000;
        if (mSolidCreditValue > 6) {
            colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2], mBgColors[3], mBgColors[4]);
            delay = 3000;
        } else if (mSolidCreditValue > 5) {
            colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2], mBgColors[3]);
            delay = 2500;
        } else if (mSolidCreditValue > 4) {
            colorAnimator.setIntValues(mBgColors[0], mBgColors[1], mBgColors[2]);
            delay = 2000;
        } else if (mSolidCreditValue > 3) {
            colorAnimator.setIntValues(mBgColors[0], mBgColors[1]);
            delay = 1500;
        }
        colorAnimator.setEvaluator(new ArgbEvaluator());
        colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mBackgroundColor = (int) animation.getAnimatedValue();
            }
        });

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(delay)
                .playTogether(creditValueAnimator, degreeValueAnimator, colorAnimator);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                isAnimFinish = false;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isAnimFinish = true;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                isAnimFinish = true;
            }
        });
        animatorSet.start();
    }

}

在color中添加颜色值:

<color name="color_red">#FF5722</color>
<color name="color_orange">#FF9800</color>
<color name="color_yellow">#FFC107</color>
<color name="color_green">#3FB830</color>
<color name="color_blue">#00BAED</color>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义view之仿支付宝芝麻信用仪表盘示例

    自定义view练习 仿支付宝芝麻信用的仪表盘 对比图: 首先是自定义一些属性,可自己再添加,挺基础的,上代码 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="RoundIndicatorView"> <!--最大数值--> <attr name="maxNum" form

  • Android自定义View制作仪表盘界面

    前言 最近我跟自定义View杠上了,甚至说有点上瘾到走火入魔了.身为菜鸟的我自然要查阅大量的资料,学习大神们的代码,这不,前两天正好在郭神在微信公众号里推送一片自定义控件的文章--一步步实现精美的钟表界面.正适合我这种菜鸟来学习,闲着没事,我就差不多依葫芦画瓢也写了一个自定义表盘View,现在纯粹最为笔记记录下来.先展示下效果图: 下面进入正题 自定义表盘属性 老规矩,先在attrs文件里添加表盘自定义属性 <declare-styleable name="WatchView"&

  • Android自定义View实现渐变色仪表盘

    前言:最近一直在学自定义View的相关知识,感觉这在Android中还是挺难的一块,当然这也是每个程序员必经之路,正好公司项目要求实现类似仪表盘的效果用于直观的显示公司数据,于是就简单的写了个demo,记录实现的过程.上篇<Android自定义View实现圆弧进度效果>简单记录了圆弧及文字的绘制,渐变色的仪表盘效果将更加升入的介绍canvas及paint的使用(如画布旋转,paint的渐变色设置等). 知识梳理 1.圆弧渐变色(SweepGradient) 2.圆弧上刻度绘制 3.指针指示当前

  • Android自定义View仿支付宝芝麻信用分仪表盘

    先看下iOS的芝麻信用分截图 这是我做的效果,还是有点差距的 支付宝9.9版本芝麻信用分的实现 首先初始化各种画笔,默认的size,padding,小圆点. (因为实在找不到原版芝麻信用的带点模糊效果的小圆点,所以只好用这个代替) //View的默认大小 defaultSize = dp2px(250); //默认Padding大小 arcDistance = dp2px(14); //外层圆环画笔 mMiddleArcPaint = new Paint(Paint.ANTI_ALIAS_FLA

  • Android实现仪表盘效果

    本文实例为大家分享了Android实现仪表盘效果的具体代码,供大家参考,具体内容如下 仪表盘效果,圆弧可变色,效果图如下: 通过自定义view实现,代码如下: public class DashboardView extends View { private int mRadius; // 画布边缘半径(去除padding后的半径) private int mStartAngle = 150; // 起始角度 private int mSweepAngle = 240; // 绘制角度 priv

  • android实现简单仪表盘效果

    本文实例为大家分享了android实现简单仪表盘效果的具体代码,供大家参考,具体内容如下 实现这个效果: 中间的文字很好写,外层的进度条就需要自定义控件了,代码如下: public class CirCleProgressBar extends View { private Paint circlePaint; private Paint textPaint; private int circleColor;//圆弧颜色 private int circleBgColor;//圆弧背景颜色 pr

  • Android绘制仪表盘指针刻度

    本文实例为大家分享了Android绘制仪表盘指针刻度的具体代码,供大家参考,具体内容如下 不废话,先看效果图: 表盘的绘制重点有两点: 1.表盘刻度的绘制 2.表盘指针旋转到指定刻度的实现 表盘刻度的绘制 刻度的绘制可以采用画线.然后循环旋转画布的方式实现,我这里通过绘制弧线,第一个刻度占1度,与第二个刻度的间距是2度,那么第二个刻度的起始角度为第一个刻度的起始角度+1度+间距2度,以此类推,循环绘制,完成刻度的绘制.实现代码如下: //绘制刻度线,通过两次不同大小圆的遮罩,达到刻度的长短粗细效

  • Android ListView弹性效果的实现方法

    关于在Android中实现ListView的弹性效果,有很多不同的方法,网上一搜,也有很多,下面贴出在项目中经常用到的两种实现ListView弹性效果的方法(基本上拿来就可以用),供大家参考: 第一种比较简单,好容易理解,只是动态改变了ListView在Y轴上的可移动距离,代码如下: import android.content.Context; import android.util.AttributeSet; import android.util.DisplayMetrics; impor

  • Android实现动画效果详解

    目前Android平台提供了两类动画一类是Tween动画,第二类就是 Frame动画,具体内容介绍请看下文: 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转.平移.放缩和渐变). 第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似. 实现动画有两种方式:一种使用XML文件(文件放在res/anim),一种直接代码搞定  1.透明度控制动画效果alpha <!-- 透明度控制动画效果alpha 浮点型值: fromAlpha 动画起始时透明

  • Android卫星菜单效果的实现方法

    Android小白第一次写博客,心情无比激动.下面给大家展示一下卫星菜单的实现. 1.简单介绍卫星菜单 在应用程序中,有很多展示菜单的方式,但其功能都是大同小异,这样一来,菜单的美观以及展示方式就显的尤为重要,卫星菜单就是很不错的一种.下面是本案例的gif图: 2.学习本案例需要的知识点 (1)动画 (2)自定义ViewGroup (3)自定义属性 a.attr.xml b.在布局中使用自定义属性 c.在代码中获取自定义属性值 3.首先分析我们的卫星菜单需要那些自定义属性并书写代码 首先,菜单可

  • Android编程滑动效果之Gallery仿图像集浏览实现方法

    本文实例讲述了Android编程滑动效果之Gallery仿图像集浏览实现方法.分享给大家供大家参考,具体如下: Android系统自带一个Gallery浏览图片的应用,通过手指拖动时能够非常流畅的显示图片,用户交互和体验都很好. 本示例就是通过Gallery和自定义的View,模仿实现一个仿Gallery图像集的图片浏览效果.效果图如下: 1.基本原理 在 Activity 中实现 OnGestureListener 的接口 onFling() 手势事件,通过自定义的 View 绘制draw()

  • Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效

    今年春节晚会没看尽兴,被支付宝集福给添了一段插曲,朋友们都在那数定时间段不停的咻一咻,哇,我咻到一个敬业福,不可能的,哈哈.那么咻一咻功能基于程序代码是怎么实现的呢?下面我们小编给大家分享本教程帮助大家学习Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效,具体内容如下所示: 先来看看这个效果 这是我的在Only上添加的效果,说实话,Only现在都还只是半成品,台面都上不了,怪自己技术不行,也太懒了 PS:这个view也是我模仿了人家的效果,参考了人家的思路写的,不是纯手撸,罪过罪过

  • Android Menu半透明效果的开发实例

    不知道大家是否用过天天动听,对于它界面上的半透明Menu效果,笔者感觉非常漂亮.下面是天天动听半透明Menu的截图,欣赏下吧: 感觉还不错吧?那么如何实现这种半透明Menu效果呢?本文就重点讨论并给出这种Menu的具体代码实现过程. 首先分析下实现这种半透明Menu所需做的工作,并进行合理分解: 1.  利用Shaper设置一个半透明圆角背景. 2.  定义Menu布局,主要就GridView,把图标都放在这个GridView. 3.  Menu事件, 通过PopupWindow或者AlertD

  • Android 吸入动画效果实现分解

    Android 吸入动画效果详解 .  这里,我要介绍的是如何在Android上面实现一个类似的效果.先看看我实现的效果图.  上图演示了动画的某几帧,其中从1 - 4,演示了图片从原始图形吸入到一个点(红色标识). 实现这样的效果,我们利用了Canvas.drawBitmapMesh()方法,这里涉及到了一个Mesh的概念. 2,Mesh的概念 Mesh表示网格,说得通俗一点,可以将画板想像成一张格子布,在这个张布上绘制图片.对于一个网格端点均匀分布的网格来说,横向有meshWidth + 1

随机推荐