Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android初級教程理論知識(第九章多媒體編程)

Android初級教程理論知識(第九章多媒體編程)

編輯:關於Android編程

多媒體概念

文字、圖片、音頻、視頻

計算機圖片大小的計算

圖片大小 = 圖片的總像素 * 每個像素占用的大小

單色圖:每個像素占用1/8個字節
16色圖:每個像素占用1/2個字節
256色圖:每個像素占用1個字節
24位圖:每個像素占用3個字節

加載大圖片到內存

Android系統以ARGB表示每個像素,所以每個像素占用4個字節,很容易內存溢出

對圖片進行縮放

獲取手機屏幕寬高(分辨率)

Display dp = getWindowManager().getDefaultDisplay();
int screenWidth = dp.getWidth();
int screenHeight = dp.getHeight();

獲取圖片寬高(分辨率)

Options opts = new Options();//創建一個位圖工廠的配置參數
//請求圖片屬性但不申請內存,解碼器不去真正的解析位圖,但是還能獲取圖片的寬高信息
由於是在Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opts);程序崩掉的,當設置了opts.inJustDecodeBounds = true;之後,bm就返回null,不會崩掉。這個時候再去對圖片做屏幕適配就可以了。
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile("sdcard/dog.jpg", opts);//返回null了,不用設置變量值
int imageWidth = opts.outWidth;//獲取圖片的寬
int imageHeight = opts.outHeight;//獲取圖片的高

圖片的寬高除以屏幕寬高,算出寬和高的縮放比例,取較大值作為圖片的縮放比例

int scale = 1;
int scaleX = imageWidth / screenWidth;//圖片寬/屏幕寬
int scaleY = imageHeight / screenHeight;//圖片高/屏幕高
if(scaleX >= scaleY && scaleX > 1){
    scale = scaleX;//獲取大的縮放比,作為圖片的最終縮放比例
}
else if(scaleY > scaleX && scaleY > 1){
    scale = scaleY;
}

按縮放比例加載圖片

//設置縮放比例
opts.inSampleSize = scale;
//這個時候有了縮放比了。因此要再一次為圖片申請內存,使用BitmapFactory去解析位圖
opts.inJustDecodeBounds = false;//真正的解析位圖
Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opts);
iv.setImageBitmap(bm);//把bitmap顯示在iv上

在內存中創建圖片的副本

直接加載的bitmap對象是只讀的,無法修改,要修改圖片只能在內存中創建出一個一模一樣的bitmap副本,然後修改副本

    //加載原圖
    Bitmap srcBm = BitmapFactory.decodeFile("sdcard/photo3.jpg");
    iv_src.setImageBitmap(srcBm);

    //創建與原圖大小一致的空白bitmap
    Bitmap copyBm = Bitmap.createBitmap(srcBm.getWidth(), srcBm.getHeight(), srcBm.getConfig());
    //定義畫筆
    Paint paint = new Paint();
    //把紙鋪在畫版上
    Canvas canvas = new Canvas(copyBm);
    //把srcBm的內容繪制在copyBm上
    canvas.drawBitmap(srcBm, new Matrix(), paint);

    iv_copy.setImageBitmap(copyBm);

對圖片進行特效處理

首先定義一個矩陣對象

Matrix mt = new Matrix();

縮放效果

//x軸縮放1倍,y軸縮放0.5倍
mt.setScale(1, 0.5f);

旋轉效果

//以copyBm.getWidth() / 2, copyBm.getHeight() / 2點為軸點,順時旋轉30度
mt.setRotate(30, copyBm.getWidth() / 2, copyBm.getHeight() / 2);

平移

//x軸坐標+10,y軸坐標+20
mt.setTranslate(10, 20);

鏡面

//把X坐標都變成負數
mt.setScale(-1, 1);
//圖片整體向右移
mt.postTranslate(copyBm.getWidth(), 0);

倒影

//把Y坐標都變成負數
mt.setScale(1, -1);
//圖片整體向下移
mt.postTranslate(0, copyBm.getHeight());

畫畫板

記錄用戶觸摸事件的XY坐標,繪制直線 * 給ImageView設置觸摸偵聽,得到用戶的觸摸事件,並獲知用戶觸摸ImageView的坐標

    iv.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            switch (event.getAction()) {
            //觸摸屏幕
            case MotionEvent.ACTION_DOWN:
                //得到觸摸屏幕時手指的坐標
                startX = (int) event.getX();
                startY = (int) event.getY();
                break;
            //在屏幕上滑動
            case MotionEvent.ACTION_MOVE:
                //用戶滑動手指,坐標不斷的改變,獲取最新坐標
                int newX = (int) event.getX();
                int newY = (int) event.getY();
                //用上次onTouch方法得到的坐標和本次得到的坐標繪制直線
                canvas.drawLine(startX, startY, newX, newY, paint);
                iv.setImageBitmap(copyBm);
                startX = newX;
                startY = newY;
                break;

            }
            return true;
        }
    });

刷子效果,加粗畫筆

paint.setStrokeWidth(8);

調色板,改變畫筆顏色

paint.setColor(Color.GREEN);

保存圖片至SD卡

FileOutputStream fos = null;
try {
    fos = new FileOutputStream(new File("sdcard/dazuo.png"));
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
//保存圖片
copyBm.compress(CompressFormat.PNG, 100, fos);
系統每次收到SD卡就緒廣播時,都會去遍歷sd卡的所有文件和文件夾,把遍歷到的所有多媒體文件都在MediaStore數據庫保存一個索引,這個索引包含多媒體文件的文件名、路徑、大小
圖庫每次打開時,並不會去遍歷sd卡獲取圖片,而是通過內容提供者從MediaStore數據庫中獲取圖片的信息,然後讀取該圖片
系統開機或者點擊加載sd卡按鈕時,系統會發送sd卡就緒廣播,我們也可以手動發送就緒廣播。這樣就解決了打開圖庫找不到剛剛存取的圖片問題了。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
sendBroadcast(intent);

音樂播放器

播放服務

播放音頻的代碼應該運行在服務中,定義一個播放服務MusicService

服務裡定義play、stop、pause、continuePlay等方法

    private void play() {
        // TODO Auto-generated method stub
        player.reset();
        try {
            player.setDataSource("sdcard/bzj.mp3");
            player.prepare();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
        player.start();

    }
    private void pause() {
        player.pause();
    }
    private void stop() {
        player.stop();
    }
    private void continuePlay() {
        player.start();
    }
把這幾個方法抽取成一個接口MusicInterface
定義一個中間人類,繼承Binder,實現MusicInterface

先start啟動MusicService,再bind

Intent intent = new Intent(this, MusicService.class);
startService(intent);
bindService(intent, conn, BIND_AUTO_CREATE);

根據播放進度設置進度條

獲取當前的播放時間和當前音頻的最長時間

int currentPosition = player.getCurrentPosition();
int duration = player.getDuration();
播放進度需要不停的獲取,不停的刷新進度條,使用計時器每500毫秒獲取一次播放進度

發消息至Handler,把播放進度放進Message對象中,在Handler中更新SeekBar的進度

Timer timer = new Timer();
timer.schedule(new TimerTask() {

    @Override
    public void run() {
        int currentPosition = player.getCurrentPosition();
        int duration = player.getDuration();
        Message msg = Message.obtain();
        //把播放進度存入Message中
        Bundle data = new Bundle();
        data.putInt("currentPosition", currentPosition);
        data.putInt("duration", duration);
        msg.setData(data);
        MainActivity.handler.sendMessage(msg);
    }
}, 5, 500);

在Activity中定義Handler

static Handler handler = new Handler(){
    public void handleMessage(android.os.Message msg) {
        //取出消息攜帶的數據
        Bundle data = msg.getData();
        int currentPosition = data.getInt("currentPosition");
        int duration = data.getInt("duration");

        //設置播放進度
        sb.setMax(duration);
        sb.setProgress(currentPosition);
    };
};

拖動進度條改變播放進度

     //給sb設置一個拖動偵聽
     sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        //停止拖動時調用
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub
            int progress = seekBar.getProgress();
            mi.seekTo(progress);
        }
        //開始拖動時調用           
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub

        }
        //拖動的時候不斷調用         
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            // TODO Auto-generated method stub

        }
    }); 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved