定制视图与属性动画的个人理解

定制视图,项目名:PersonDraw

效果就是能手动在屏幕上绘制图形。
1.创建的视图类DesignView.java继承自View类。

public class DesignView extends View {
    private static final String TAG="DesignView";
    private Box mBox;
    private List<Box> mBoxlist=new ArrayList<>();
    private Paint mBoxPaint;
    private Paint MBackgroundPaint;

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

    public DesignView(Context context, AttributeSet attrs){
        super(context,attrs);
        mBoxPaint=new Paint();
        mBoxPaint.setColor(0x22ff0000);

        MBackgroundPaint=new Paint();
        MBackgroundPaint.setColor(0xfff8efe0);

    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        PointF current=new PointF(event.getX(),event.getY());
        String action="";
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                action="ACTION_DOWN";
                mBox=new Box(current);
                mBoxlist.add(mBox);
                break;
            case MotionEvent.ACTION_MOVE:
                action="ACTION_MOVE";
                if(mBox!=null){
                    mBox.setMxian(current);
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_UP:
                action="ACTION_UP";
                mBox=null;
                break;
            case MotionEvent.ACTION_CANCEL:
                action="ACTION_CANCEL";
                mBox=null;
                break;
        }
        Log.i(TAG,action+current.x+current.y);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {//真正实现绘图的方法
       canvas.drawPaint(MBackgroundPaint);
        for (Box box:mBoxlist){
            float left = Math.min(box.getMyuan().x, box.getMxian().x);
            float right = Math.max(box.getMyuan().x, box.getMxian().x);
            float top = Math.min(box.getMyuan().y, box.getMxian().y);
            float bottom = Math.max(box.getMyuan().y, box.getMxian().y);
            canvas.drawRect(left,top,right,bottom,mBoxPaint);
        }
    }
}

两个构造方法的目的是让视图可从代码或者布局文件进行实例化。
首先是重写onTouchEvent()方法来记录四个动作,这里使用了PointF类记录屏幕的x和y坐标。还有这里创建了一个Box类是用来表示我定义的矩形框两个x,y坐标的。只要Action_down发生就以当前坐标新建一个Box类,并且存进数组中,当手指移动就能获取第二个坐标进行矩形的绘制。调用invalidate()方法是为了强制重新绘制,并再次调用onDraw()方法,这样才能实时地看到我们绘制的矩形框。

public class Box {
    private PointF myuan;
    private PointF mxian;

    public PointF getMyuan() {
        return myuan;
    }

    public void setMyuan(PointF myuan) {
        this.myuan = myuan;
    }

    public PointF getMxian() {
        return mxian;
    }

    public void setMxian(PointF mxian) {
        this.mxian = mxian;
    }

    public Box(PointF ori) {

       myuan=ori;
        mxian=ori;
    }
}

而在XML文件当中可以这样使用:

<phtotoshow.com.example.persondraw.DesignView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

这里再说说这里用到的Canvas类和Paint类这安卓系统的两大绘制类:

Canvas:所有绘制操作,在那里绘制以及绘制什么。
Paint:绘制图形的特征,什么字体,线条颜色。
再这个Designview中,在构造方法初始化Paint类,并设置好颜色。
然后就是在Draw()方法中填充canvas。并完成相应的坐标计算,最后调用 canvas.drawRect()方法绘制。

属性动画

实现的是点击屏幕日落日出的动画。
首先为了显示出一个圆,在drawable文件下添加上一个xml文件,
内容是:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/bright_sun"/>

</shape>

下面这个是整个场景的布局:

在这里插入图片描述
这样就能看到具体的布局。下面就是在具体的Fragment中显示出来,在activity中托管fragment:

public class SunsetActivity extends SingleFragmentActivity {
    @Override
    protected Fragment createFragment() {
        return SunsetFragment.newInstance();
    }
}

public class SunsetFragment extends Fragment {
    private View mSceneView;
    private View mSunView;
    private View mSkyView;
    private int mBlueSkyColor;
    private int mSunsetSkyColor;
    private int mNightSkyColor;
    private int flag=0;
    public static SunsetFragment newInstance() {


        return new SunsetFragment();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v=inflater.inflate(R.layout.fragment_sunset,container,false);
        mSceneView=v;
        mSunView=v.findViewById(R.id.sun);
        mSkyView=v.findViewById(R.id.sky);
        Resources resources = getResources();//获取颜色
        mBlueSkyColor = resources.getColor(R.color.blue_sky);
        mSunsetSkyColor = resources.getColor(R.color.sunset_sky);
        mNightSkyColor = resources.getColor(R.color.night_sky);

        mSceneView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switch (flag) {
                    case 0:
                        startAnimation();
                        flag=1;
                        break;
                    case 1:
                        startAnimation1();
                        flag=0;
                        break;
                }
            }
        });
        return v;

    }

    private void startAnimation(){
        float start=mSunView.getTop();
        float end=mSkyView.getHeight();
        //第一个动画
        ObjectAnimator heightAnimator=ObjectAnimator.ofFloat(mSunView,"y",start,end)
                .setDuration(3000);
        heightAnimator.setInterpolator(new AccelerateDecelerateInterpolator());//改变速度

//第二个动画
        ObjectAnimator skyAnimator=ObjectAnimator.ofInt(mSkyView,"backgroundColor",mBlueSkyColor,mSunsetSkyColor)
                .setDuration(3000);
        skyAnimator.setEvaluator(new ArgbEvaluator());//让颜色变化变得自然
        heightAnimator.start();//动画开始
        //第三个动画

        ObjectAnimator nightSkyAnimator = ObjectAnimator
                .ofInt(mSkyView, "backgroundColor", mSunsetSkyColor, mNightSkyColor)
                .setDuration(1500);
        nightSkyAnimator.setEvaluator(new ArgbEvaluator());
//动画集
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet
                .play(heightAnimator)
                .with(skyAnimator)
                .before(nightSkyAnimator);
        animatorSet.start();
    }

    private void startAnimation1(){
        float sunYStart = mSunView.getTop();
        float sunYEnd = mSkyView.getHeight();
        flag=0;

        ObjectAnimator nightSkyAnimator = ObjectAnimator
                .ofInt(mSkyView, "backgroundColor", mNightSkyColor,mSunsetSkyColor )
                .setDuration(1500);
        nightSkyAnimator.setEvaluator(new ArgbEvaluator());

        ObjectAnimator heightAnimator = ObjectAnimator
                .ofFloat(mSunView, "y", sunYEnd, sunYStart)
                .setDuration(3000);
        heightAnimator.setInterpolator(new AccelerateInterpolator());

        ObjectAnimator sunsetSkyAnimator = ObjectAnimator
                .ofInt(mSkyView, "backgroundColor", mSunsetSkyColor, mBlueSkyColor)
                .setDuration(3000);
        sunsetSkyAnimator.setEvaluator(new ArgbEvaluator());
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet
                .play(heightAnimator)
                .with(nightSkyAnimator)
                .before(sunsetSkyAnimator);
        animatorSet.start();



    }
}

其余的不多说,主要是定义了3个View类,分别太阳,天空以及海面。
通过调用startAnimation()方法获取视图的顶部坐标位置,从而为下面对太阳下落的距离进行计算。下一步是创建模拟太阳的ObiectAnimator对象,这个就是属性动画制作对象,该对象的setInterpolator方法可实现不同的动画特效,这里是太阳慢慢下落再加速坠落。能发现这里一共有两个ObiectAnimator对象,第二个是实现天空色彩的变换。而其中
skyAnimator.setEvaluator(new ArgbEvaluator());//让颜色变化变得自然,用于计算颜色变化的递进值。
最后就是使用动画集AnimatorSet类来进行多个动画的播放,同样是调用strart()方法来启动。

结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值