天天看点

AnimatedPathView实现自定义图片标签,让图片动起来

且看个效果图:

AnimatedPathView实现自定义图片标签,让图片动起来
AnimatedPathView实现自定义图片标签,让图片动起来
AnimatedPathView实现自定义图片标签,让图片动起来

要实现我们这样的效果,首先分析下,线条的绘制和中间圆圈的实现,以及文字的绘制。

AnimatedPathView实现自定义图片标签,让图片动起来

float percentage = 0.0f;  

patheffect effect = new dashpatheffect(new float[]{pathlength, pathlength}, pathlength - pathlength*percentage);  

这里贴出animatedpathview的完整代码:

AnimatedPathView实现自定义图片标签,让图片动起来

public class animatedpathview extends view {  

    private paint mpaint;  

    private path mpath;  

    private int mstrokecolor = color.parsecolor("#ff6c6c");  

    private int mstrokewidth = 8;  

    private float mprogress = 0f;  

    private float mpathlength = 0f;  

    private float circlex = 0f;  

    private float circley = 0f;  

    private int radius = 0;  

    private string pathtext="化妆包...";  

    private int textx,texty;  

    public animatedpathview(context context) {  

        this(context, null);  

        init();  

    }  

    public animatedpathview(context context, attributeset attrs) {  

        this(context, attrs, 0);  

    public animatedpathview(context context, attributeset attrs, int defstyle) {  

        super(context, attrs, defstyle);  

        typedarray a = context.obtainstyledattributes(attrs, r.styleable.animatedpathview);  

        mstrokecolor = a.getcolor(r.styleable.animatedpathview_pathcolor, color.parsecolor("#ff6c6c"));  

        mstrokewidth = a.getinteger(r.styleable.animatedpathview_pathwidth, 8);  

        a.recycle();  

    private void init() {  

        mpaint = new paint();  

        mpaint.setcolor(mstrokecolor);  

        mpaint.setstyle(paint.style.stroke);  

        mpaint.setstrokewidth(mstrokewidth);  

        mpaint.setantialias(true);  

        setpath(new path());  

    public void setpath(path p) {  

        mpath = p;  

        pathmeasure measure = new pathmeasure(mpath, false);  

        mpathlength = measure.getlength();  

    public void setpathtext(string pathtext,int textx,int texty ) {  

        this.pathtext=pathtext;  

        this.textx=textx;  

        this.texty=texty;  

    public void setpath(float[]... points) {  

        if (points.length == 0)  

            throw new illegalargumentexception("cannot have zero points in the line");  

        path p = new path();  

        p.moveto(points[0][0], points[0][1]);  

        for (int i = 1; i < points.length; i++) {  

            p.lineto(points[i][0], points[i][1]);  

        }  

        //将第一个xy坐标点作为绘制的原点  

        circlex = points[0][0] - radius / 2;  

        circley = points[0][1] - radius / 2;  

        setpath(p);  

    public void setpercentage(float percentage) {  

        if (percentage < 0.0f || percentage > 1.0f)  

            throw new illegalargumentexception("setpercentage not between 0.0f and 1.0f");  

        mprogress = percentage;  

        invalidate();  

    public void scalepathby(float x, float y) {  

        matrix m = new matrix();  

        m.postscale(x, y);  

        mpath.transform(m);  

    public void scalecircleradius(int radius) {  

        this.radius = radius;  

    @override  

    protected void ondraw(canvas canvas) {  

        super.ondraw(canvas);  

        //绘制圆形  

//        drawcircle(canvas);  

        //绘线条  

        drawpatheffect(canvas);  

        //绘制文字  

        drawtext(canvas);  

        canvas.restore();  

    private void drawtext(canvas canvas) {  

        mpaint.settextsize(28);  

        mpaint.setcolor(color.parsecolor("#ffffff"));  

        if (canvas!=null&& !textutils.isempty(pathtext)){  

            canvas.drawtext(pathtext,textx,texty,mpaint);  

    private void drawpatheffect(canvas canvas) {  

        patheffect patheffect = new dashpatheffect(new float[]{mpathlength, mpathlength}, (mpathlength - mpathlength * mprogress));  

        mpaint.setpatheffect(patheffect);  

        mpaint.setstrokewidth(4);  

        canvas.save();  

        canvas.translate(getpaddingleft(), getpaddingtop());  

        canvas.drawpath(mpath, mpaint);  

    private void drawcircle(canvas canvas) {  

        int strokenwidth = 25;  

        mpaint.setstrokewidth(strokenwidth);  

        canvas.drawcircle(circlex, circley, radius , mpaint);  

    protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {  

        super.onmeasure(widthmeasurespec, heightmeasurespec);  

        int widthsize = measurespec.getsize(widthmeasurespec);  

        int heightsize = measurespec.getsize(heightmeasurespec);  

        int widthmode = measurespec.getmode(widthmeasurespec);  

        int heightmode = measurespec.getmode(widthmeasurespec);  

        int measuredwidth, measuredheight;  

        if (widthmode == measurespec.at_most)  

            throw new illegalstateexception("animatedpathview cannot have a wrap_content property");  

        else  

            measuredwidth = widthsize;  

        if (heightmode == measurespec.at_most)  

            measuredheight = heightsize;  

        setmeasureddimension(measuredwidth, measuredheight);  

}  

AnimatedPathView实现自定义图片标签,让图片动起来

public class pointview extends framelayout {  

    private context mcontext;  

    private list<pointscalebean> points;  

    private framelayout layoupoints;  

    private animatedpathview animatedpath;  

    private int radius=10;  

    private string text="图文标签 $99.00";  

    public pointview(context context) {  

    public pointview(context context, attributeset attrs) {  

    public pointview(context context, attributeset attrs, int defstyleattr) {  

        super(context, attrs, defstyleattr);  

        initview(context, attrs);  

    private void initview(context context, attributeset attrs) {  

        this.mcontext = context;  

        view imgpointlayout = inflate(context, r.layout.layout_point, this);  

        layoupoints = (framelayout) imgpointlayout.findviewbyid(r.id.layoupoints);  

        animatedpath=(animatedpathview) imgpointlayout.findviewbyid(r.id.animated_path);  

    public void addpoints(int width, int height) {  

        addpoint(width, height);  

    public void setpoints(list<pointscalebean> points) {  

        this.points = points;  

    private void addpoint(int width, int height) {  

        layoupoints.removeallviews();  

        for (int i = 0; i < points.size(); i++) {  

            double width_scale = points.get(i).widthscale;  

            double height_scale = points.get(i).heightscale;  

            linearlayout view = (linearlayout) layoutinflater.from(mcontext).inflate(r.layout.layout_img_point, this, false);  

            imageview imageview = (imageview) view.findviewbyid(r.id.imgpoint);  

            imageview.settag(i);  

            animationdrawable animationdrawable = (animationdrawable) imageview.getdrawable();  

            animationdrawable.start();  

            layoutparams layoutparams = (layoutparams) view.getlayoutparams();  

            layoutparams.leftmargin = (int) (width * width_scale);  

            layoutparams.topmargin = (int) (height * height_scale);  

//            imageview.setonclicklistener(this);  

            layoupoints.addview(view, layoutparams);  

        initview();  

        initpathanimated();  

    private void initpathanimated() {  

        viewtreeobserver observer = animatedpath.getviewtreeobserver();  

        if(observer != null){  

            observer.addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() {  

                @override  

                public void ongloballayout() {  

                    animatedpath.getviewtreeobserver().removeglobalonlayoutlistener(this);  

                    animatedpath.scalecircleradius(radius);  

                    animatedpath.scalepathby(animatedpath.getwidth()/2,animatedpath.getheight()/2);  

                    float[][] points = new float[][]{  

                            {animatedpath.getwidth()/2-radius/2,animatedpath.getheight()/2-radius/2},  

                            {animatedpath.getwidth()/2- uiutils.dp2px(mcontext,30), animatedpath.getheight()/2- uiutils.dp2px(mcontext,40)},  

                            {animatedpath.getwidth()/2-uiutils.dp2px(mcontext,150), animatedpath.getheight()/2- uiutils.dp2px(mcontext,40)},  

                    };  

                    animatedpath.setpath(points);  

//                    animatedpath.setpathtext(text,animatedpath.getwidth()/2-uiutils.dp2px(mcontext,150), animatedpath.getheight()/2- uiutils.dp2px(mcontext,50));  

                }  

            });  

    private void initview() {  

        animatedpath.setonclicklistener(new view.onclicklistener() {  

            @override  

            public void onclick(view view) {  

                objectanimator anim = objectanimator.offloat(view, "percentage", 0.0f, 1.0f);  

                anim.setduration(2000);  

                anim.setinterpolator(new linearinterpolator());  

                anim.start();  

            }  

        });  

上面对应的布局和资源文件:

layou_point.xml

AnimatedPathView实现自定义图片标签,让图片动起来

<?xml version="1.0" encoding="utf-8"?>  

<framelayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:layout_width="match_parent"  

    android:layout_height="wrap_content"  

    >  

    <com.yju.app.widght.path.animatedpathview  

        android:id="@+id/animated_path"  

        android:layout_width="match_parent"  

        android:layout_height="wrap_content"  

        />  

    <framelayout  

        android:id="@+id/layoupoints"  

        android:layout_gravity="center" />  

</framelayout>  

layout_img_point.xml

AnimatedPathView实现自定义图片标签,让图片动起来

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"  

    android:layout_height="match_parent"  

    android:gravity="center"  

    android:orientation="vertical">  

    <imageview  

        android:id="@+id/imgpoint"  

        android:layout_width="wrap_content"  

        android:src="@drawable/point_img" />  

</linearlayout>  

文中用到的anim就是帧动画了,

AnimatedPathView实现自定义图片标签,让图片动起来

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  

    android:oneshot="false">  

    <item  

        android:drawable="@drawable/point_img1"  

        android:duration="100" />  

    ....省略n多图片资源  

        android:drawable="@drawable/point_img13"  

</animation-list>  

而最后我们只需要在我们自己的mainactivity中添加简单的代码既可实现上面的效果:

AnimatedPathView实现自定义图片标签,让图片动起来

private void initpointview() {  

        list<pointscalebean> list=new arraylist<>();  

        pointscalebean point=new pointscalebean();  

        point.widthscale = 0.36f;  

        point.heightscale = 0.75f;  

        list.add(point);  

        pointview.setpoints(list);  

        pointview.addpoints(viewgroup.layoutparams.match_parent,viewgroup.layoutparams.match_parent);  

AnimatedPathView实现自定义图片标签,让图片动起来

对于布局我是这么做的,将view的父布局的背景加一个图片,实际的开发中大家可以写一个相对的布局,这个就能实现实时的效果了,好了就写到这里,有疑问请留言或者加群(278792776)。

继续阅读