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();
			}});}}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章