画布Canvas:Android框架API提供了一组2D描画API,使用这些API能够在一个画布(canvas)上渲染自己的定制图形,也能够修改那些既存的View对象,来定制它们的外观和视觉效果。在绘制2D图形时,通常要使用 把图形直接绘制在一个画布对象上(Canvas对象)。这种方法,要亲自调用相应类的onDraw()方法(把图形传递给Canvas对象),或者调用Canvas对象的一个draw…()方法(如drawPicture())。在这个过程中,还可以控制任何动画。
下面介绍下画布Canvas的用法:Canvas的英语意思就是帆布、画布的意思。顾名思义根据该类可以创建一个基本的画布,除了在画布上绘制之外,还需要设置一些关于画布的属性,比如,画布的颜色、尺寸等。画布设定好之后,还要参加一个画笔类再画布上创作:Paint paint = new Paint();一般要变为成员变量。
Canvas和Paint提供了如下一些方法:
Canvas canvas = new Canvas(copyBitmap); 创建一个画布的实例,传入一个bitmap的实例,必须以该实例的基础图片上作画,之前就需要把一个drawable的imageview的控件设置为bitmap。
canvas.drawBitmap(srcBitmap, new Matrix(), paint); 开始作画的参数传入,设置具体画布。
canvas.rotate(45.0f); 画布旋转角度为45度,传入为float类型。
canvas.drawPoint(200,200, paint); 在坐标(200,200)的位置画一个点。
canvas.drawColor(Color.BLACK); 设置Canvas的背景颜色为黑色,注意要与画笔颜色有点区别
canvas.drawLine(100,100,600,600,paint); 绘制直线,前2个参数为开始点坐标,后二个参数为结束点坐标。
canvas.drawRect(new Rect(150, 75, 260, 120), paint);绘制矩形 ,对角线点绘制矩形,只需要确定矩形对角线的起始点和结束点。将二点坐标传入
到Rect的实例中,矩形api:Rect(int left, int top, int right, int bottom)Create a new rectangle with the specified coordinates.
canvas.drawRoundRect(new RectF(200,200,1000,800),15,15,paint) ;参数前面一样是矩形的创建参数,后面第一个15为圆角椭圆X轴的值,第二个
15为圆角椭圆Y轴的值。若相等就是为R为15的圆角。圆角矩形api:
RectF(float left, float top, float right, float bottom)Create a new rectangle with the specified coordinates.
canvas.drawCircle(900,900,500,paint); 绘制圆形,参数为:圆心X轴坐标,圆心Y轴指标,圆的半径
drawOval(float left, float top,float right, float bottom,,Paint paint) 绘制椭圆:设置椭圆的边界顶点,float left, float top,第一个椭圆长边或者短边的顶点,
float right, float bottom为椭圆长边或者短边的顶点。
paint.setColor(Color.RED);设置画笔颜色
paint.setStrokeWidth(20);设置画笔粗细
通过Path类的实例创建三角形
绘制三角形或者多边形,通过点的方法
path.MoveTo(0,0);设置画笔起点;path.LineTo(8,0);设置画笔到该点的路径;path.LineTo(8,6);设置路径(8,0)到(8,6);
path.close();将绘制的线形成封闭空间.canvas.drawPath(path, paint);画出三角形
paint.setStyle(Paint.Style.STROKE);风格样式为描边;paint.setStyle(Paint.Style.FILL)风格样式为填充
paint.setStyle(Paint.Style.FILL_AND_STROKE): 填充且描边
paint.setAntiAlias(true);是否设置抗锯齿,设置抗锯齿会使图像边缘更清晰一些,锯齿痕迹不会那么明显。
例子:一个小画板案列:
package com.example.point;
import java.io.File;
import java.io.FileOutputStream;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView iv;
private Bitmap srcBitmap;
private Bitmap copyBitmap;
private Canvas canvas;
private Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1,找到控件
iv = (ImageView) findViewById(R.id.iv);
//2 把bg转换成bitmap
srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hua);
//2.1创建模板
copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//2.2以copybitmap为模板 创建一个画布
canvas = new Canvas(copyBitmap);
//2.3创建画笔
paint = new Paint();
//2,4开始画
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
//3,把copebitmap显示到iv上
iv.setImageBitmap(copyBitmap);
//4,设置iv一个触摸事件
iv.setOnTouchListener(new OnTouchListener() {
int startX = 0;
int startY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
//5,获取手指触摸的事件类型
int action = event.getAction();
//6,具体判断是那个类型
switch (action) {
case MotionEvent.ACTION_DOWN://按下
//7,获取手指按下的坐标
startX= (int) event.getX();
startY=(int) event.getY();
break;
case MotionEvent.ACTION_MOVE://移动
//8,获取停止的坐标
int stopX = (int) event.getX();
int stopY = (int) event.getY();
//9,画线
canvas.drawLine(startX, startY, stopX, stopY, paint);
//9.1更新坐标
startX = stopX;
startY = stopY;
//10,再更新UI
iv.setImageBitmap(copyBitmap);
break;
case MotionEvent.ACTION_UP://抬起
break;
}
return true;
}
});
}
//点击按钮改变画笔的颜色为红色
public void click1(View v) {
paint.setColor(Color.RED);
}
//让画笔变粗
public void click2(View v) {
paint.setStrokeWidth(20);
}
//保存文件
public void click3(View v) {
/*
* format 保存图片的格式
*
* quality 保存照片的质量
*
* stream 定义流保存
*/
try {
File file = new File(Environment.getExternalStorageDirectory().getPath(),"huahua.png");
FileOutputStream fos;
fos = new FileOutputStream(file);
copyBitmap.compress(CompressFormat.PNG, 100, fos);
//发送广播更新图库,模拟发送sd卡被卸载重新装载 图库会收到广播加载sd卡图片
Intent intent = new Intent();
//设置action
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
//设置data
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
//发送无序广播
sendBroadcast(intent);
fos.close();
Toast.makeText(getApplicationContext(), "成功保存", 3).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
fragment的用法
Fragment的生命周期, 每一个fragments 都有自己的一套生命周期回调方法和处理自己的用户输入事件。他可以比如成一个小的activity。
介绍一下相比activity多出的方法:
onAttach()
当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
onCreateView()
当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。必须要实现该方法。
onActivityCreated()
当activity的onCreated()方法返回后调用此方法。
onDestroyView()
当fragment的layout被销毁时被调用。
onDetach()
当fragment被从activity中删掉时被调用
要记住的有两点:
fragment1布局:
fragment2布局:
在分别写出fragment1和fragment2继承与fragment类
package com.itheima.fragment;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
//定义一个Fragment
public class Fragment2 extends Fragment {
//当用户第一次画ui的时候调用 要显示Fragment自己的内容 setContentView(R.layout.activity_main);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//[1]通过打气筒把一个布局转换成view对象
View view = inflater.inflate(R.layout.fragment2, null);
return view;
}
}
package com.itheima.fragment;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
//定义一个Fragment
public class Fragment1 extends Fragment {
//当用户第一次画ui的时候调用 要显示Fragment自己的内容 setContentView(R.layout.activity_main);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//[1]通过打气筒把一个布局转换成view对象
View view = inflater.inflate(R.layout.fragment1, null);
return view;
}
}
微信的fragmen:
联系人fragment:
发现fragment:
Me的fragment:
package com.example.weixin;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Toast;
public class WxFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_wx, null);
view.findViewById(R.id.btn_test).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "我被点击了", 1).show();
}
});
return view;
}
}
联系人的fragment类:
package com.example.weixin;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ContactFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contact, null);
return view;
}
}
发现的fragment类:
package com.example.weixin;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class DiscoverFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_discover, null);
return view;
}
}
我的fragment类:
package com.example.weixin;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MeFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_me, null);
return view;
}
}
package com.example.weixin;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1找到控件
Button btn_contact = (Button) findViewById(R.id.btn_contact);
Button btn_discover = (Button) findViewById(R.id.btn_discover);
Button btn_wx = (Button) findViewById(R.id.btn_wx);
Button btn_me = (Button) findViewById(R.id.btn_me);
// 2设置点击事件
btn_contact.setOnClickListener(this);
btn_discover.setOnClickListener(this);
btn_wx.setOnClickListener(this);
btn_me.setOnClickListener(this);
}
@Override
public void onClick(View v) {
// 3判断哪一个点击事件
//4,获取fragment的管理者
FragmentManager fragmentManager =getFragmentManager();
//5,开启事务
FragmentTransaction transaction =fragmentManager.beginTransaction();
switch (v.getId()) {
case R.id.btn_wx://显示微信fragment
transaction.replace(R.id.ll, new WxFragment());
break;
case R.id.btn_contact://显示联系人fragment
transaction.replace(R.id.ll, new ContactFragment());
break;
case R.id.btn_discover://显示发现fragment
transaction.replace(R.id.ll, new DiscoverFragment());
break;
case R.id.btn_me://显示我fragment
transaction.replace(R.id.ll, new MeFragment());
break;
}
//6,一定要提交事务
transaction.commit();
}
}
package com.example.communication;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1,开启Fragment的管理者
FragmentManager fragmentManager =getFragmentManager();
//2,开启事务
FragmentTransaction transaction = fragmentManager.beginTransaction();
//3,动态替换
transaction.replace(R.id.ll1,new Fragment1(),"f1");//给fragment1设置标签f1
transaction.replace(R.id.ll2,new Fragment2(),"f2");//给fragment2设置标签f2
//4,提交事务
transaction.commit();
}
}
fragment1类:通过activity公共桥梁完成修改
package com.example.communication;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Toast;
public class Fragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment1, null);
//1,找到按钮 设置点击事件
view.findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "修改了数据", 1).show();
//2修改fragment的textview的值
Fragment2 f2 = (Fragment2)getActivity().getFragmentManager().findFragmentByTag("f2");
f2.setText("hahahahah");
}
});
return view;
}
}
fragment2类:
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Fragment2 extends Fragment {
private TextView tv;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment2, null);
tv = (TextView) view.findViewById(R.id.tv);
return view;
}
//修改text方法
public void setText(String content){
tv.setText(content);
}
}
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//执行我们的动画
iv = (ImageView) findViewById(R.id.iv);
//设置一个点击事件
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "哈哈 你点不到我", 1).show();
}
});
}
//点击按钮 实现iv 透明的效果 动画
public void click1(View v) {
//1.0意味着着完全不透明 0.0意味着完全透明
AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);
aa.setDuration(2000); //设置动画执行的时间
aa.setRepeatCount(1); //设置重复的次数
aa.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
//iv开始执行动画
iv.startAnimation(aa);
}
//点击按钮 实现iv 执行一个旋转 动画
public void click2(View v) {
//fromDegrees 开始角度 toDegrees 结束角度
// RotateAnimation ra = new RotateAnimation(0, 360);
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000); //设置动画执行的时间
ra.setRepeatCount(1); //设置重复的次数
ra.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
//iv开始执行动画
iv.startAnimation(ra);
}
//点击按钮进行一个缩放动画
public void click3(View v) {
ScaleAnimation sa = new ScaleAnimation(1.0f,2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(2000); //设置动画执行的时间
sa.setRepeatCount(1); //设置重复的次数
sa.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
//iv开始执行动画
iv.startAnimation(sa);
}
//位移动画
public void click4(View v){
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.2f);
ta.setDuration(2000); //设置动画执行的时间
ta.setFillAfter(true);//当动画结束后 动画停留在结束位置
//开始动画
iv.startAnimation(ta);
}
//动画一起飞
public void click5(View v){
AnimationSet set = new AnimationSet(false);
//透明动画
AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);
aa.setDuration(2000); //设置动画执行的时间
aa.setRepeatCount(1); //设置重复的次数
aa.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
//旋转动画
RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(2000); //设置动画执行的时间
ra.setRepeatCount(1); //设置重复的次数
ra.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
//缩放
ScaleAnimation sa = new ScaleAnimation(1.0f,2.0f, 1.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(2000); //设置动画执行的时间
sa.setRepeatCount(1); //设置重复的次数
sa.setRepeatMode(Animation.REVERSE);//设置动画执行的模式
TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.2f);
ta.setDuration(2000); //设置动画执行的时间
ta.setFillAfter(true);//当动画结束后 动画停留在结束位置
//添加动画
set.addAnimation(aa);
set.addAnimation(ra);
set.addAnimation(sa);
set.addAnimation(ta);
//最后一步 要记得 执行动画
iv.startAnimation(set);
}
}
rotate.xml 旋转动画
scale.xml 缩放动画
translate.xml 平移动画
综合效果动画:set.xml
package com.example.propertyanimator;
import android.os.Bundle;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//加载的布局
setContentView(R.layout.activity_main);
//找到iv 执行动画
iv = (ImageView) findViewById(R.id.iv);
//设置了一个点击事件
iv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点不到我", 0).show();
}
});
// iv.setTranslationX(translationX)
// iv.setScaleX(scaleX)
// iv.setAlpha(alpha)
// iv.setRotation(rotation)
}
//位移动画
public void translate(View v){
//创建属性动画
/**
* target 执行的目标
* propertyName 属性名字 The name of the property being animated.
* float... values 可变参数
*/
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 50,20,100);
oa.setDuration(2000);
oa.start(); //开始动画
}
//缩放动画
public void scale(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2);
oa.setDuration(2000);
oa.start();
}
//实现透明的效果
public void alpha(View v){
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1,0,1);
oa.setDuration(2000);
oa.start();
}
//实现旋转的效果
public void rotate(View v){
// ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 360);
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationX", 0, 180, 90, 360);
oa.setDuration(2000);
oa.start();
}
//一起飞
public void fly(View v){
AnimatorSet as = new AnimatorSet();
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 50, 20, 100);
ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "scaleY", 0.1f, 2, 1, 2);
ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.5f, 0, 1);
ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360);
as.setDuration(2000);//执行动画时长
as.setTarget(iv);//iv执行动画
//往集合中添加动画
//挨个飞
as.playSequentially(oa, oa2, oa3, oa4);
//一起飞
// as.playTogether(oa, oa2, oa3, oa4);
as.start();
}
//使用xml的方式创建属性动画
public void playxml(View v){
ObjectAnimator oa = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.oanimator);
//设置执行目标
oa.setTarget(iv);
oa.start();//开始执行
}
}
同样也可以在xml中创建一个动画效果来展示,需要在res下创建一个animator目录。