Android课堂笔记(十一)——图形、音频视频

目录

一.使用图形

1.了解图形基础

2.绘制二维图形

2.1 绘制标准图形

2.2 绘制跟随移动的图形

2.3 让用户自己绘制图形

二.添加音频、视频

1.基础知识

2.播放本地音乐

3.播放SD卡 / 网络音乐(外部URI)

4.播放列表音乐(内部URI)


一.使用图形

  • 图形:最基本的多媒体组件
  • 一些图形工具:如画布,颜色过滤器,点和矩阵,可以直接处理和控制屏幕绘制,生成动画
  • OpenGL:是一个标准,定义了可生成二维和三维计算机图形的应用的跨语言,跨平台的API

1.了解图形基础

  • Canvas(画布):指定画布 和 绘制图像,被写入位图
  • Paint(画笔):指定画笔,包括画笔颜色、样式等
  • Bitmap(位图):每个画布都有至少一个 Bitmap对象存储绘制的内容,位图图像使用 像素 创建图形
  • 绘制时需要以下基本组件:
  1. 容纳像素的位图
  2. 位图:容纳绘画调用的画布,它会被写入位图
  3. 画的东西:要绘制的形状,例如矩形、路径和文本
  4. 画笔:描述绘图颜色和样式的颜料
  • Canvas 类:提供多种方法绘制简单图形,还能转换、缩放画布图像,并保存和恢复其绘图状态
  • Paint 对象:为在画布上绘制的图形指定属性,如颜色样式填充阴影文本字体属性
  1. public Paint() :默认设置的画笔(使用最多)
  2. public Paint(Paint paint):自定义画笔属性的画笔
  • Bitmap 类为图像提供了 低级接口,而 Canvas 类为图像提供了 高级接口

2.绘制二维图形

  • 在画布上绘图:
  1. View类:简单图形动画,不需要高帧率时,提供预定义画布,扩展 View类 ,实现 onDraw()  ,绘制视图并传递一个 Canvas 对象,要绘制画布,必需调用 invalidate() 方法 刷新视图
  2. SurfaceView类:高帧率动画,需要实现 SurfaceHolder.Callback 接口
  • Canvas 类的一些方法,可以在 onDraw() 方法 中调用它们绘制图像和图形:

方法

描述

drawBitmap (Bitmap bitmap,

float left, float top, Paint

paint)

在指定座标上以指定的颜料 绘制位图

drawCircle (float cx, float cy,

float radius, Paint paint)

以指定的座标为圆心,

按指定的半径使用指定的颜料 画圆

drawRect (float left, float

top, float right, float bottom,

Paint paint)

以指定的颜料画 矩形

其左上角位于 (x1, y1),右下角位于 (x2, y2)

  • 让用户通过在屏幕上单击、拖放来绘制图形,需要捕获各种移动事件:
  1. ACTION_DOWN
  2. ACTION_MOVE
  3. ACTION_UP

2.1 绘制标准图形

  • 图形文件一般放在 帧布局管理器,因为可以层叠
// DrawView.java,不在主活动文件中写绘画代码
public class DrawView extends View{ // 从View类派生出一个自己的类,用于绘制图形
	Paint p;
	public DrawView(Context context, AttributeSet attrs) {
		super(context, attrs);
		p=new Paint();         // 创建画笔对象,采用默认设置
		p.setColor(Color.RED); // 设置画笔颜色为红色
		p.setStrokeWidth(5);   // 设置画笔的宽度
		p.setStyle(Paint.Style.STROKE); // 设置画笔的样式,描边轮廓
	}
	@Override // 构造函数会自动调用,invlidate()刷新视图也会被调用
	protected void onDraw(Canvas canvas) {     // 重写onDraw(),在这里完成图形绘制
		canvas.drawColor(Color.BLACK);     // 设置帆布颜色为黑色
		canvas.drawCircle(100,100,50, p);  // 画圈
		p.setColor(Color.YELLOW);          // 设置画笔颜色为黄色
		p.setStyle(Paint.Style.FILL);      // 填充
		canvas.drawRect(200, 200, 300, 300, p);  // 画矩形
		p.setColor(0xff0000aa);//设置画笔颜色为蓝色不透明
		canvas.drawLine(100, 100, 250, 250, p);  // 画直线
		p.setTextAlign(Paint.Align.LEFT);        // 字体左对齐
		p.setAntiAlias(true);                    // 采用抗锯齿功能
		canvas.drawText("你吃饭了吗?",30,300,p);  // 绘制文本
        }}
// 布局文件 自定义DrawView引用 静态修改
    <com.Lyrelion.makedrawview.DrawView
        android:id="@+id/drawView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
==================================================================================
①+②可,①+③可,②③不可共存
==================================================================================
// MainActivity.java 动态修改
public class MainActivity extends Activity {
	private static final AttributeSet attrs = null; 
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FrameLayout frameLayout = (android.widget.FrameLayout) findViewById(R.id.frameLayout);
		frameLayout.addView(new DrawView(this, attrs)); // 把自定义画布添加到指定视图
    }}
  • 简单绘图:

2.2 绘制跟随移动的图形

  • BitmapFactory.decodeResource()方法:解码图片资源,形成位图对象
// MyView.java
public class MyView extends View{
	Paint p;
	float x,y; // 定义两个变量x,y,用于存储圆心座标
	Bitmap bm;
	public MyView(Context context, AttributeSet attrs) {
		// 解码图片资源,形成位图对象...
		bm=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);}
	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.BLACK);
     //	canvas.drawCircle(x, y,30, p);
		canvas.drawBitmap(bm,x,y,p);
	}
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if(event.getAction()==MotionEvent.ACTION_MOVE){ // 如果发生移动
			x=event.getX();
			y=event.getY(); // 获取事件发生时 x和y座标
			invalidate();   // 刷新当前视图,会自动调用onDraw()
		}
		/*if(event.getAction()==MotionEvent.ACTION_DOWN){
			x=event.getX();
			y=event.getY(); //获取事件发生的时候的x和y座标
			invalidate();
		}*/
		return true; // 该事件本方法处理了,不需要继续传播
	}}
// 布局文件
    <com.Lyrelion.makemyview.MyView
        android:id="@+id/myView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
  • 跟随鼠标移动的小人:

2.3 让用户自己绘制图形

public class MyView extends View{
	Paint p;
	Path path; // 表示一个你要绘制的路径
	public MyView(Context context, AttributeSet attrs) {
      // 初始化...
	}
	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.BLACK);
		if(path!=null)
			canvas.drawPath(path,p);
	}
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch(event.getAction()){    // 判断触摸事件的动作
		case MotionEvent.ACTION_DOWN: // 如果是按下
			path=new Path();
			path.moveTo(event.getX(),event.getY()); // moveTo():移动到要绘制路径的起点
			break;
		case MotionEvent.ACTION_MOVE: // 如果是移动
			path.lineTo(event.getX(),event.getY()); // lineTo():绘制路线到指定的终点
			invalidate();
			break;}
		return true;
	}}
  • 用户可以自己随便画:

二.添加音频、视频

1.基础知识

  • 多媒体框架 最重要的组件是 Android.media.MediaPlayer类
  • Android 提供了多媒体库,它能 播放(重点)和录制 各种媒体格式
  • android.media.MediaRecorder类:录制音频/视频
  • Android 仿真器没有获取音频视频的硬件,但实际移动设备可用于测试此类功能
  • MediaPlayer类 只能单独播放音频,如果想播放视频,还需要:SurfaceView类 配合使用
  • 播放存储在 不同媒体源中的 媒体,如:
  1. 本地资源: res/raw/ 静态资源文件
  2. 内部 URI:从内容解析器接收到的 ,比如读取系统自带的音乐
  3. 外部 URL:从因特网上的流服务器获取的文件,或者SD卡获取的文件等等
  • MediaPlayer 类的一些方法:
  • getCurrentPosition():获取当前播放的位置
  • getDuration():获取媒体时长
  • pause(), prepare(), release():暂停、预播放、释放资源(音乐停止后,重新播放会从头开始)
  • reset():重置到未初始化状态
  • seekTo(int msec):查找指定的时间位置,如设置歌曲开始播放的位置
  • setDataSource(String path):通过 路径 加载资源文件
  • setDataSource(Context context, Uri uri):通过 URI 加载资源文件
  • setOnCompletionListener(MediaPlayer.OnCompletionListener listener):设置完成监听器
  • setOnPreparedListener(MediaPlayer.OnPreparedListener listener):设置预播放监听器
  • start():开始 / 继续播放
  • stop():停止播放

2.播放本地音乐

  • 播放 本地资源 音频,此资源保存在 res/raw/ 目录中:
public class MainActivity extends Activity {
	Button play,pause,stop;    // 声明组件
	MediaPlayer mp;            // 声明播放器对象
	boolean isStop=true;       // 设置播放状态为关闭
    // 获取组件,注册监听...
    class ButtonListener implements OnClickListener{
		@Override
		public void onClick(View v) {
			switch(v.getId()){
			case R.id.play:
				if(isStop){ // 若处于停止状态,则重新实例化MediaPlayer,重新播放
					mp=MediaPlayer.create(MainActivity.this,R.raw.music2);
					mp.setLooping(true); // 设置循环播放
					isStop=false;        // 非关闭状态
				}
				mp.start();             // 播放音乐
				play.setEnabled(false); // 开始播放后,设置播放按钮不可用
				pause.setEnabled(true); // 开始播放后,设置暂停按钮可用
				stop.setEnabled(true);
				break;
			case R.id.pause:
				mp.pause();             // 暂停音乐
				play.setEnabled(true); 
				pause.setEnabled(false);
				stop.setEnabled(false);
				break;
			case R.id.stop:
				mp.stop();              // 关闭音乐
				isStop=true;            // 停止了,所以isStop的值设为true
				mp.release();           // 释放掉关联的资源
				play.setEnabled(true);
				pause.setEnabled(false);
				stop.setEnabled(false);
				break;
			}}}}
  •  

3.播放SD卡 / 网络音乐(外部URI)

  • 播放 存储在外部存储设备(SD 卡)中的音频 / 播放 外部(如网络)的音频:
  • DDMS SD卡中的文件导入(Push)/ 文件导出(Pull):
public class MainActivity extends Activity {
	ImageView start, pause, stop; //1:声明组件对象
	MediaPlayer mp;
	boolean isStop=true;
		start = (ImageView) findViewById(R.id.start); //2:获取组件对象 设置监听器...
		pause = (ImageView) findViewById(R.id.pause);
		stop = (ImageView) findViewById(R.id.stop);

		mp = new MediaPlayer();
		try {                       // 从网络上加载音乐资源 需要联网 且授予应用联网权限
			mp.setDataSource("http://mp3.9ku.com/mp3/558/557854.mp3");
		} catch (Exception e) {}
		/*try {                     // /mnt/sdcard 从sd卡获取音乐资源
			String path = Environment.getExternalStorageDirectory() + "/"
					+ "music2.mp3"; // 设置外部存储器地址,这个操作需要授权
			mp.setDataSource(path); // 通过路径加载路径
		} catch (Exception e) {}*/
	}
	class MyListener implements OnClickListener {
		@Override
		public void onClick(View v) {
			switch (v.getId()) {
			case R.id.start:
				if(isStop){         // 如果是关闭状态
					try{
					 // mp.reset();
					  mp.prepare(); // 预加载
					  mp.seekTo(0); // 将歌曲播放位置指定到开始
					  isStop=false; 
					}catch(Exception e){}}
				mp.start();
				break;
			case R.id.pause:
				mp.pause();
				break;
			case R.id.stop:
				isStop=true;
				mp.stop();
				mp.release();      // 释放资源,导致音乐停止后,重新播放会从头开始
				break;
			}}}}

4.播放列表音乐(内部URI)

  • 适配器四个参数:上下文,ListView的布局编号,具体样式编号,数据列表
  • adapter = new ArrayAdapter<String>(MainActivity.this, R.layout.item, R.id.tvItem, songList);
  • 用适配器给音乐列表填充内容:lv.setAdapter(adapter);
public class MainActivity extends Activity {
	Button btnStop;
	ListView lv;                          // 音乐列表
	ArrayList<String> songList;           // 定义一个List集合,用于存储歌曲名称
	ArrayList<String> pathList;           // 定义一个List集合,用于存储歌曲路径
	Uri uri = Media.EXTERNAL_CONTENT_URI; // 指定要访问的内容提供者的Uri,获取本机音乐
	ContentResolver cr;                   // 调用内容提供者
	ArrayAdapter<String> adapter;         // 数据适配器,用于加载数据给ListView
	MediaPlayer mp;                       // 定义音乐播放器
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btnStop = (Button) findViewById(R.id.button1);
		lv = (ListView) findViewById(R.id.listView1);
		songList = new ArrayList<String>(); // 实例化歌名集合
		pathList = new ArrayList<String>(); // 实例化数组集合
		cr = getContentResolver(); // getContentResolver():实例化内容解析器实例
		mp = new MediaPlayer();    // 实例化音乐播放器

		String[] columns = { Media.TITLE, Media.DATA }; // 定义音乐的名字、信息数组
		Cursor c = cr.query(uri, columns, null, null, null);
		while (c.moveToNext()) { // 遍历 Cursor对象
			songList.add(c.getString(0)); // 将歌曲名称(第一列)加入到songList集合
			pathList.add(c.getString(1)); // 将该行第二列的路径加入到pathList集合
		}
		// 四个参数:上下文,ListView的布局编号,具体样式编号,数据列表
		adapter = new ArrayAdapter<String>(MainActivity.this, R.layout.item,
				R.id.tvItem, songList);
		lv.setAdapter(adapter); // 用适配器给音乐列表填充内容
		// 处理ListView的选项点击事件
		lv.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				try {
					mp.reset(); // 每次重置MediaPlayer,才能重新指定资源,播放新歌曲
					// 设置数据源,从pathList获取position位置的歌曲的路径
					mp.setDataSource(pathList.get(position));
					mp.prepare();
					mp.start();
				} catch (Exception e) {}}});
		btnStop.setOnClickListener(new OnClickListener() { // 点击停止播放
			@Override
			public void onClick(View v) {
				mp.stop();
			}});}}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章