Android视图绘画与属性动画
转载至我的个人博客:自定义视图中绘制一个图形
PointF
用于保存两个浮点坐标x,y
float x,y;PointF location...location=new PointF(x,y)location=new PointF();location.set(x,y);
Paint
存储绘制信息,决定如何绘制
...boxPaint=new Paint();boxPaint.setColor(Color.RED);backgrounPaint=new Paint();backgrounPaint.setColor(Color.BLACK);canvas.drawPaint(backgrounPaint);canvas.drawRect(left,top,right,bottom,boxPaint);
Canvas
拥有需要的所有绘制操作
....@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制自定义视图的背景色 canvas.drawPaint(backgrounPaint); for(Boxer boxer:boxers){ float left=Math.min(boxer.getOrigiin().x,boxer.getCurrent().x); float right=Math.max(boxer.getOrigiin().x,boxer.getCurrent().x); float top=Math.min(boxer.getOrigiin().y,boxer.getCurrent().y); float bottom=Math.max(boxer.getOrigiin().y,boxer.getCurrent().y); //画出一个矩形 canvas.drawRect(left,top,right,bottom,boxPaint); }}
实例:绘制一个矩形
Boxer.class
import android.graphics.PointF;public class Boxer { private PointF origiin; private PointF current; public Boxer(PointF origiin){ this.origiin=origiin; this.current=origiin; } public void setCurrent(PointF current){ this.current=current; } public PointF getCurrent() { return current; } public PointF getOrigiin() { return origiin; }}
BoxVieWer.class
import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PointF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import java.util.List;public class BoxVieWer extends View { private static final String TAG=BoxVieWer.class.getSimpleName(); private Boxer boxer; private List boxers; private Paint boxPaint; private Paint backgrounPaint; public BoxVieWer(Context context) { super(context); } public BoxVieWer(Context context, @Nullable AttributeSet attrs) { super(context, attrs); boxers=new ArrayList<>(); boxPaint=new Paint(); boxPaint.setColor(Color.RED); backgrounPaint=new Paint(); backgrounPaint.setColor(Color.BLACK); } @Override public boolean onTouchEvent(MotionEvent event) { PointF pointF=new PointF(event.getX(),event.getY()); switch(event.getAction()){ case MotionEvent.ACTION_DOWN: boxer=new Boxer(pointF); boxers.add(boxer); break; case MotionEvent.ACTION_MOVE: if(boxer!=null){ boxer.setCurrent(pointF); invalidate(); } break; case MotionEvent.ACTION_UP: boxer=null; break; case MotionEvent.ACTION_CANCEL: boxer=null; break; } return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPaint(backgrounPaint); for(Boxer boxer:boxers){ float left=Math.min(boxer.getOrigiin().x,boxer.getCurrent().x);; float right=Math.max(boxer.getOrigiin().x,boxer.getCurrent().x); float top=Math.min(boxer.getOrigiin().y,boxer.getCurrent().y); float bottom=Math.max(boxer.getOrigiin().y,boxer.getCurrent().y); canvas.drawRect(left,top,right,bottom,boxPaint); } }}
ViewerActivity.class
import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import io.githubs.grooters.luffy.R;public class ViewerActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_drawer); }}
view_drawer.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <luffy_viewer.BoxVieWer android:layout_width="match_parent" android:layout_height="match_parent" />LinearLayout>
Drawable
Selector
<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/pic1" /> <item android:state_window_focused="false" android:drawable="@drawable/pic1" /> <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/pic2" /> <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic3" /> <item android:state_selected="true" android:drawable="@drawable/pic4" /> <item android:state_focused="true" android:drawable="@drawable/pic5" /> selector>
Shape
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="false"> <stroke android:color="@color/colorAccent" android:width="1dp"/> <size android:width="20dp" android:height="20dp"/>shape>
android:shape="rectangle"
android:shape="line"
<solid android:color="@color/colorAccent"/>
Selector与Shape结合使用
以下代码摘抄自互联网
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false"> <shape android:shape="rectangle"> <corners android:radius="5dp" /> <solid android:color="@color/white" /> <stroke android:width="1dp" android:color="@color/blue" /> shape> item> <item android:state_pressed="true"> <shape android:shape="rectangle"> <corners android:radius="5dp" /> <solid android:color="@color/white" /> <stroke android:width="1dp" android:color="@color/green" /> shape> item>selector>
属性动画
ObjectAnimator
//从sunStart移动到skyHeightObjectAnimator.ofFloat(sun,"Y",sunStart,skyHeight);//从当前位置向下移动200,回到初始位置再向上移动100ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(sun, "Y", 0, 200, -100,0);
设置动画时间
objectAnimator.setDuration(5000);
eg:
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(sun,"y",sunStart,skyHeight).setDuration(2000);objectAnimator.start();
注意:
在OnCreate()objectAnimator.start();是无效的,因为在OnCreate()中AnimationDrawable还没有完全的与ImageView绑定
TimeInterpolator
//由慢变快objectAnimator.setInterpolator(new AccelerateInterpolator());//由快变慢objectAnimator.setInterpolator(new DecelerateInterpolator());
颜色渐变
int first=getResources().getColor(R.color.colorPrimary,getTheme());int second=getResources().getColor(R.color.colorAccent,getTheme());int last=getResources().getColor(R.color.black,getTheme());ObjectAnimator skyAnimation = ObjectAnimator.ofInt(sky,"backgroundColor",first,second,last);skyAnimation.setDuration(5000);skyAnimation.setEvaluator(new ArgbEvaluator());skyAnimation.start();
AnimatorSet
可将动画放在一起播放动画集
AnimatorSet set=new AnimatorSet();set.play(firstAnimation).with(nextAnimation).before(lastAnimation);set.start();
state list AnimatorSet
使按钮按下和松开具有浮动效果,改变z值
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="10dp" android:valueType="floatType"/> item> <item android:state_pressed="false"> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0dp" android:valueType="floatType"/> item>selector>
将以上xml文件放入animator文件夹
然后通过android:stateListAnimator为组件设置动画
circular revel
将View像墨滴一样舒展开来
@Overridepublic void onClick(View view) { // 获取FloatingActionButton的中心点的坐标 int centerX = (view.getLeft() + view.getRight()) / 2; int centerY = (view.getTop() + view.getBottom()) / 2; Log.i(TAG,"centerX:"+centerX); // 获取扩散的半径 float finalRadius = (float) Math.hypot((double) centerX, (double) centerY); // 定义揭露动画 Animator mCircularReveal = ViewAnimationUtils.createCircularReveal(revelView, centerX, centerY, 0, finalRadius); // 设置动画持续时间,并开始动画 mCircularReveal.setDuration(4000).start();}
其中view为触发组件,revelView为需要揭露出来地新地View,Math.hypot勾股定理求斜边
shared element transition
共享元素交换,又称为hero transaction,可实现点击列表中的一张图片,令它以动画形式独立显示在一个新的activity/fragment中
@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS); setContentView(R.layout.activity_animationer); final ImageView sun=findViewById(R.id.sunImage); Button tranButton=findViewById(R.id.button_animation); tranButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent=new Intent(AnimatioNer.this,ImagerActivity.class); ViewCompat.setTransitionName(sun,"image"); ActivityOptionsCompat optionsCompat=ActivityOptionsCompat.makeSceneTransitionAnimation(AnimatioNer.this,sun,"image"); AnimatioNer.this.startActivity(intent,optionsCompat.toBundle()); } });}
getWindow().requestFeature(Window.FEATURE_ACTIVITY_TRANSITIONS)
必须写在setContentView前
ViewCompat.setTransitionName(View view, String transictionName )
view为需要共享的资源,这里是图片sun,transictionName的字符串要和布局(原布局和共享布局)中组件transitionName属性值一样,eg:
<ImageView android:id="@+id/sunImage" android:layout_gravity="center" android:background="@drawable/sun" android:transitionName="image" android:layout_width="50dp" android:layout_height="50dp"/>
由于共享布局是共享主布局的sunImage图片,所以共享布局中也必须由图片控件,并带有transitionName=”image”属性
optionsCompat=ActivityOptionsCompat.makeSceneTransitionAnimation(Activity activity,View view,String transictionName)
更多相关文章
- Android(安卓)开发笔记 动画效果 --Animation
- Android(安卓)动画显示文字与bitmap的BadgeView
- Android(安卓)自定义dialog出入场动画
- Android手动画柱状图的例子
- Android中的矢量动画
- Activity切换动画无效(android:windowIsTranslucent)影响(androi
- android开机动画
- Android(安卓)集成百度地图实现设备定位
- Android(安卓)属性动画(Property Animation) 完全解析 (上)