Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發本地及網絡Mp3音樂播放器(七)循環模式與專輯倒影

Android開發本地及網絡Mp3音樂播放器(七)循環模式與專輯倒影

編輯:關於Android編程

實現功能:
順序播放
隨機播放
單曲循環
PlayActivity(獨立音樂播放界面)的專輯封面圖片的倒影效果

另外,我打算開始找工作,如果沈陽或周邊城市公司有意,也請與我聯系。

實現效果如圖:

\

\

\

\

\

實現代碼如下:

PlayService如下:

 

package com.iwanghang.drmplayer;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;

import com.iwanghang.drmplayer.utils.MediaUtils;
import com.iwanghang.drmplayer.vo.Mp3Info;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 音樂播放的服務組件
 * 實現功能:
 * 播放
 * 暫停
 * 下一首
 * 上一首
 * 獲取當前歌曲的播放進度
 *
 * 需要在AndroidManifest.xml添加以下代碼:
 *
 *
 *
 * 實現功能(播放模式play_mode):
 * 順序播放
 * 隨機播放
 * 單曲循環
 */
public class PlayService extends Service implements OnCompletionListener,OnErrorListener{
    private MediaPlayer mPlayer;
    private int currentPosition;//當前正在播放的歌曲的位置
    ArrayList mp3Infos;

    private MusicUpdatrListener musicUpdatrListener;

    //創建一個單實力的線程,用於更新音樂信息
    private ExecutorService es = Executors.newSingleThreadExecutor();

    //播放模式
    public static final int ORDER_PLAY = 1;//順序播放
    public static final int RANDOM_PLAY = 2;//隨機播放
    public static final int SINGLE_PLAY = 3;//單曲循環
    private int play_mode = ORDER_PLAY;//播放模式,默認為順序播放

    /**
     * @param play_mode
     * ORDER_PLAY = 1;//順序播放
     * RANDOM_PLAY = 2;//隨機播放
     * SINGLE_PLAY = 3;//單曲循環
     */
    //set方法
    public void setPlay_mode(int play_mode) {
        this.play_mode = play_mode;
    }

    //get方法
    public int getPlay_mode() {
        return play_mode;
    }

    private boolean isPause = false;//歌曲播放中的暫停狀態

    public boolean isPause(){
        return isPause;
    }

    public PlayService() {
    }

    public int getCurrentPosition(){
        return currentPosition;
    }

    private Random random = new Random();//創建隨機對象
    //MediaPlayer.Completion 播放完成 實現播放下一首功能
    //播放完成以後,判斷播放模式(曲目循環方式)
    //為了實現循環後,可以顯示音樂信息,需要在PlayAcivity的change裡添加對應代碼
    @Override
    public void onCompletion(MediaPlayer mp) {
        switch (play_mode){
            case ORDER_PLAY://順序播放
                next();//下一首
                break;
            case RANDOM_PLAY://隨機播放
                //currentPosition = random.nextInt(mp3Infos.size());//隨機下標為mp3Infos.size()
                //play(currentPosition);
                play(random.nextInt(mp3Infos.size()));
                break;
            case SINGLE_PLAY://單曲循環
                play(currentPosition);
                break;
            default:
                break;
        }
    }
    //MediaPlayer.Error 播放錯誤 處理實現播放下一首功能出現的錯誤
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        mp.reset();//重啟
        return false;
    }

    //內部類PlayBinder實現Binder,得到當前PlayService對象
    class PlayBinder extends Binder{
        public PlayService getPlayService(){
            System.out.println("PlayService #1 " + PlayService.this);
            return PlayService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new PlayBinder();//通過PlayBinder拿到PlayService,給Activity調用
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mPlayer = new MediaPlayer();
        mPlayer.setOnCompletionListener(this);//注冊播放完成事件
        mPlayer.setOnErrorListener(this);//注冊播放錯誤事件
        mp3Infos = MediaUtils.getMp3Infos(this);//獲取Mp3列表
        es.execute(updateSteatusRunnable);//更新進度值
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //回收線程
        if (es!=null && !es.isShutdown()){//當進度值等於空,並且,進度值沒有關閉
            es.shutdown();
            es = null;
        }
    }

    //利用Runnable來實現多線程
    /**
     * Runnable
     * Java中實現多線程有兩種途徑:繼承Thread類或者實現Runnable接口.
     * Runnable接口非常簡單,就定義了一個方法run(),繼承Runnable並實現這個
     * 方法就可以實現多線程了,但是這個run()方法不能自己調用,必須由系統來調用,否則就和別的方法沒有什麼區別了.
     * 好處:數據共享
     */
    Runnable updateSteatusRunnable = new Runnable() {//更新狀態
        @Override
        public void run() {
            //不斷更新進度值
            while (true){
                //音樂更新監聽不為空,並且,媒體播放不為空,並且媒體播放為播放狀態
                if(musicUpdatrListener!=null && mPlayer!=null && mPlayer.isPlaying()){
                    musicUpdatrListener.onPublish(getCurrentProgress());//獲取當前的進度值
                }
                try {
                    Thread.sleep(500);//500毫秒更新一次
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    //播放
    public void play(int position){
        if (position>=0 && position=mp3Infos.size()-1){//如果超出最大值,(因為第一首是0),說明已經是最後一首
            currentPosition = 0;//回到第一首
        }else {
            currentPosition++;//下一首
        }
        play(currentPosition);
    }

    //上一首 previous
    public void prev(){
        if (currentPosition-1<0){//如果上一首小於0,說明已經是第一首
            currentPosition = mp3Infos.size()-1;//回到最後一首
        }else {
            currentPosition--;//上一首
        }
        play(currentPosition);
    }

    //默認開始播放的方法
    public void start(){
        if (mPlayer!=null && !mPlayer.isPlaying()){//判斷當前歌曲不等於空,並且沒有在播放的狀態
            mPlayer.start();

        }
    }

    //獲取當前是否為播放狀態,提供給MyMusicListFragment的播放暫停按鈕點擊事件判斷狀態時調用
    public boolean isPlaying(){
        if (mPlayer!=null){
            return mPlayer.isPlaying();
        }
        return false;
    }

    //獲取當前的進度值
    public int getCurrentProgress(){
        if(mPlayer!=null && mPlayer.isPlaying()){//mPlayer不為空,並且,為播放狀態
            return mPlayer.getCurrentPosition();
        }
        return 0;
    }
    //getDuration 獲取文件的持續時間
    public int getDuration(){
        return mPlayer.getDuration();
    }
    //seekTo 尋找指定的時間位置
    public void seekTo(int msec){
        mPlayer.seekTo(msec);
    }

    //更新狀態的接口(PlayService的內部接口),並在BaseActivity中實現
    public interface MusicUpdatrListener{//音樂更新監聽器
        public void onPublish(int progress);//發表進度事件(更新進度條)
        public void onChange(int position); //更新歌曲位置.按鈕的狀態等信息
        //聲明MusicUpdatrListener後,添加set方法
    }

    //set方法
    public void setMusicUpdatrListener(MusicUpdatrListener musicUpdatrListener) {
        this.musicUpdatrListener = musicUpdatrListener;
    }
}

 

PlayActivity如下:

 

package com.iwanghang.drmplayer;

import android.graphics.Bitmap;
import android.os.Bundle;

import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;


import com.iwanghang.drmplayer.utils.ImageUtils;
import com.iwanghang.drmplayer.utils.MediaUtils;
import com.iwanghang.drmplayer.vo.Mp3Info;

import java.util.ArrayList;

import static com.iwanghang.drmplayer.PlayService.ORDER_PLAY;
import static com.iwanghang.drmplayer.PlayService.RANDOM_PLAY;
import static com.iwanghang.drmplayer.PlayService.SINGLE_PLAY;

/**
 *PlayActivity 點擊MyMusicListFragment(本地音樂)底部UI中的專輯封面圖片打開的Activity
 */
public class PlayActivity extends BaseActivity implements OnClickListener{
    private TextView textView1_title;//歌名
    private ImageView imageView1_ablum;//專輯封面圖片
    private SeekBar seekBar1;//進度條
    private TextView textView1_start_time,textView1_end_time;//開始時間,結束時間
    private ImageView imageView1_play_mode;//菜單
    private ImageView imageView3_previous,imageView2_play_pause,imageView1_next;//上一首,播放暫停,下一首
    private ImageView imageView1_ablum_reflection;//專輯封面圖片倒影

    private ArrayList mp3Infos;
    //private int position;//當前播放的位置
    private boolean isPause = false;//當前播放的是否為暫停狀態
    private static final int UPDATE_TIME = 0x1;//更新播放事件的標記

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music_play);
        //初始化界面信息
        textView1_title = (TextView) findViewById(R.id.textView1_title);//歌名
        imageView1_ablum = (ImageView) findViewById(R.id.imageView1_ablum);//專輯封面圖片
        seekBar1 = (SeekBar) findViewById(R.id.seekBar1);//進度條
        textView1_start_time = (TextView) findViewById(R.id.textView1_start_time);//開始時間
        textView1_end_time = (TextView) findViewById(R.id.textView1_end_time);//結束時間
        imageView1_play_mode = (ImageView) findViewById(R.id.imageView1_play_mode);//菜單
        imageView3_previous = (ImageView) findViewById(R.id.imageView3_previous);//上一首
        imageView2_play_pause = (ImageView) findViewById(R.id.imageView2_play_pause);//播放暫停
        imageView1_next = (ImageView) findViewById(R.id.imageView1_next);//下一首
        imageView1_ablum_reflection = (ImageView) findViewById(R.id.imageView1_ablum_reflection);//專輯封面圖片倒影
        //注冊按鈕點擊監聽事件
        imageView1_play_mode.setOnClickListener(this);
        imageView2_play_pause.setOnClickListener(this);
        imageView3_previous.setOnClickListener(this);
        imageView1_next.setOnClickListener(this);


        mp3Infos = MediaUtils.getMp3Infos(this);
        //bindPlayService();//綁定服務,異步過程,綁定後需要取得相應的值,來更新界面
        myHandler = new MyHandler(this);

        //以下直接調用change()是不行的,因為異步問題,會發生NullPointerException空指針異常
        //從MyMusicListFragment的專輯封面圖片點擊時間傳過來的position(當前播放的位置)
        //position = getIntent().getIntExtra("position",0);
        //change(position);

        //通過在BaseActivity中綁定Service,添加如下代碼實現change()
        //musicUpdatrListener.onChange(playService.getCurrentProgeress());

        //從MyMusicListFragment的專輯封面圖片點擊時間傳過來的isPause(當前播放的是否為暫停狀態)
        //isPause = getIntent().getBooleanExtra("isPause",false);
    }

    //把播放服務的綁定和解綁放在onResume,onPause裡,好處是,每次回到當前Activity就獲取一次播放狀態
    @Override
    protected void onResume() {
        super.onResume();
        bindPlayService();
    }

    @Override
    protected void onPause() {
        super.onPause();
        unbindPlayService();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindPlayService();//解綁服務
    }

    //Handler用於更新已經播放時間
    private static MyHandler myHandler;
    static class MyHandler extends Handler{
        private PlayActivity playActivity;
        public MyHandler(PlayActivity playActivity){
            this.playActivity = playActivity;
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (playActivity!=null){
                switch (msg.what){
                    case UPDATE_TIME://更新時間(已經播放時間)
                        playActivity.textView1_start_time.setText(MediaUtils.formatTime(msg.arg1));
                        break;
                }
            }
        }
    }

    @Override
    public void publish(int progress) {
        //以下是是直接調用線程,但是不能這樣做,會報錯,線程異常
        //textView1_start_time.setText(MediaUtils.formatTime(progress));
        //所以,我們需要使用Handler
        Message msg = myHandler.obtainMessage(UPDATE_TIME);//用於更新已經播放時間
        msg.arg1 = progress;//用於更新已經播放時間
        myHandler.sendMessage(msg);//用於更新已經播放時間

        seekBar1.setProgress(progress);
    }

    @Override
    public void change(int position) {
        //if (this.playService.isPlaying()) {//獲取是否為播放狀態
        System.out.println("PlayActivity #100 position = " + position);
        Mp3Info mp3Info = mp3Infos.get(position);
        textView1_title.setText(mp3Info.getTitle());//設置歌名
        //獲取專輯封面圖片
        Bitmap albumBitmap = MediaUtils.getArtwork(this, mp3Info.getId(), mp3Info.getAlbumId(), true, false);
        //改變播放界面專輯封面圖片
        imageView1_ablum.setImageBitmap(albumBitmap);
        textView1_end_time.setText(MediaUtils.formatTime(mp3Info.getDuration()));//設置結束時間
        imageView2_play_pause.setImageResource(R.mipmap.app_music_pause);//設置暫停圖片
        seekBar1.setProgress(0);//設置當前進度為0
        seekBar1.setMax((int)mp3Info.getDuration());//設置進度條最大值為MP3總時間
        if (playService.isPlaying()){
            imageView2_play_pause.setImageResource(R.mipmap.app_music_pause);
        }else {
            imageView2_play_pause.setImageResource(R.mipmap.app_music_play);
        }

        if(imageView1_ablum != null) {
            imageView1_ablum_reflection.setImageBitmap(ImageUtils.createReflectionBitmapForSingle(albumBitmap));//顯示倒影
        }
        switch (playService.getPlay_mode()){
            case ORDER_PLAY://順序播放
                imageView1_play_mode.setImageResource(R.mipmap.app_mode_order);
                //imageView2_play_pause.setTag(ORDER_PLAY);
                break;
            case PlayService.RANDOM_PLAY://隨機播放
                imageView1_play_mode.setImageResource(R.mipmap.app_mode_random);
                //imageView2_play_pause.setTag(RANDOM_PLAY);
                break;
            case PlayService.SINGLE_PLAY://單曲循環
                imageView1_play_mode.setImageResource(R.mipmap.app_mode_single);
                //imageView2_play_pause.setTag(SINGLE_PLAY);
                break;
            default:
                break;
        }
    }

        //點擊事件
        @Override
        public void onClick(View v) {
            switch (v.getId()){
            case R.id.imageView2_play_pause: {//播放暫停按鈕
                if (playService.isPlaying()) {//如果是播放狀態
                    imageView2_play_pause.setImageResource(R.mipmap.app_music_play);//設置播放圖片
                    playService.pause();
                } else {
                    if (playService.isPause()) {
                        imageView2_play_pause.setImageResource(R.mipmap.app_music_pause);//設置暫停圖片
                        playService.start();//播放事件
                    } else {
                        //只有打開APP沒有點擊任何歌曲,同時,直接點擊暫停播放按鈕時.才會調用
                        playService.play(0);
                    }
                }
                break;
            }
            case R.id.imageView1_next:{//下一首按鈕
                playService.next();//下一首
                break;
            }
            case R.id.imageView3_previous:{//上一首按鈕
                playService.prev();//上一首
                break;
            }
            case R.id.imageView1_play_mode:{//循環模式按鈕
                //int mode = (int) imageView1_play_mode.getTag();
                switch (playService.getPlay_mode()){
                    case ORDER_PLAY:
                        imageView1_play_mode.setImageResource(R.mipmap.app_mode_random);
                        //imageView1_play_mode.setTag(RANDOM_PLAY);
                        playService.setPlay_mode(RANDOM_PLAY);
                        Toast.makeText(getApplicationContext(),"隨機播放",Toast.LENGTH_SHORT).show();
                        break;
                    case RANDOM_PLAY:
                        imageView1_play_mode.setImageResource(R.mipmap.app_mode_single);
                        //imageView1_play_mode.setTag(SINGLE_PLAY);
                        playService.setPlay_mode(SINGLE_PLAY);
                        Toast.makeText(getApplicationContext(),"單曲循環",Toast.LENGTH_SHORT).show();
                        break;
                    case SINGLE_PLAY:
                        imageView1_play_mode.setImageResource(R.mipmap.app_mode_order);
                        //imageView1_play_mode.setTag(ORDER_PLAY);
                        playService.setPlay_mode(ORDER_PLAY);
                        Toast.makeText(getApplicationContext(),"順序播放",Toast.LENGTH_SHORT).show();
                        break;
                }
                break;
            }
            default:
                break;
        }
    }
}

 

ImageUtils如下:
package com.iwanghang.drmplayer.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

/**
 * 圖片工具類
 * Created by iwanghang on 16/4/25.
 */
public class ImageUtils {
    /**圖片的八個位置**/
    public static final int TOP = 0;			//上
    public static final int BOTTOM = 1;			//下
    public static final int LEFT = 2;			//左
    public static final int RIGHT = 3;			//右
    public static final int LEFT_TOP = 4;		//左上
    public static final int LEFT_BOTTOM = 5;	//左下
    public static final int RIGHT_TOP = 6;		//右上
    public static final int RIGHT_BOTTOM = 7;	//右下

    /**
     * 圖像的放大縮小方法
     * @param src		源位圖對象
     * @param scaleX	寬度比例系數
     * @param scaleY	高度比例系數
     * @return 返回位圖對象
     */
    public static Bitmap zoomBitmap(Bitmap src, float scaleX, float scaleY) {
        Matrix matrix = new Matrix();
        matrix.setScale(scaleX, scaleY);
        Bitmap t_bitmap = Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), matrix, true);
        return t_bitmap;
    }

    /**
     * 圖像放大縮小--根據寬度和高度
     * @param src
     * @param width
     * @param height
     * @return
     */
    public static Bitmap zoomBimtap(Bitmap src, int width, int height) {
        return Bitmap.createScaledBitmap(src, width, height, true);
    }

    /**
     * 將Drawable轉為Bitmap對象
     * @param drawable
     * @return
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        return ((BitmapDrawable)drawable).getBitmap();
    }


    /**
     * 將Bitmap轉換為Drawable對象
     * @param bitmap
     * @return
     */
    public static Drawable bitmapToDrawable(Bitmap bitmap) {
        Drawable drawable = new BitmapDrawable(bitmap);
        return drawable;
    }

    /**
     * Bitmap轉byte[]
     * @param bitmap
     * @return
     */
    public static byte[] bitmapToByte(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        return out.toByteArray();
    }

    /**
     * byte[]轉Bitmap
     * @param data
     * @return
     */
    public static Bitmap byteToBitmap(byte[] data) {
        if(data.length != 0) {
            return BitmapFactory.decodeByteArray(data, 0, data.length);
        }
        return null;
    }

    /**
     * 繪制帶圓角的圖像
     * @param src
     * @param radius
     * @return
     */
    public static Bitmap createRoundedCornerBitmap(Bitmap src, int radius) {
        final int w = src.getWidth();
        final int h = src.getHeight();
        // 高清量32位圖
        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Paint paint = new Paint();
        Canvas canvas = new Canvas(bitmap);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(0xff424242);
        // 防止邊緣的鋸齒
        paint.setFilterBitmap(true);
        Rect rect = new Rect(0, 0, w, h);
        RectF rectf = new RectF(rect);
        // 繪制帶圓角的矩形
        canvas.drawRoundRect(rectf, radius, radius, paint);

        // 取兩層繪制交集,顯示上層
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        // 繪制圖像
        canvas.drawBitmap(src, rect, rect, paint);
        return bitmap;
    }

    /**
     * 創建選中帶提示圖片
     * @param context
     * @param srcId
     * @param tipId
     * @return
     */
    public static Drawable createSelectedTip(Context context, int srcId, int tipId) {
        Bitmap src = BitmapFactory.decodeResource(context.getResources(), srcId);
        Bitmap tip = BitmapFactory.decodeResource(context.getResources(), tipId);
        final int w = src.getWidth();
        final int h = src.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Paint paint = new Paint();
        Canvas canvas = new Canvas(bitmap);
        //繪制原圖
        canvas.drawBitmap(src, 0, 0, paint);
        //繪制提示圖片
        canvas.drawBitmap(tip, (w - tip.getWidth()), 0, paint);
        return bitmapToDrawable(bitmap);
    }

    /**
     * 帶倒影的圖像
     * @param src
     * @return
     */
    public static Bitmap createReflectionBitmap(Bitmap src) {
        // 兩個圖像間的空隙
        final int spacing = 4;
        final int w = src.getWidth();
        final int h = src.getHeight();
        // 繪制高質量32位圖
        Bitmap bitmap = Bitmap.createBitmap(w, h + h / 2 + spacing, Config.ARGB_8888);
        // 創建燕X軸的倒影圖像
        Matrix m = new Matrix();
        m.setScale(1, -1);
        Bitmap t_bitmap = Bitmap.createBitmap(src, 0, h / 2, w, h / 2, m, true);

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        //	繪制原圖像
        canvas.drawBitmap(src, 0, 0, paint);
        // 繪制倒影圖像
        canvas.drawBitmap(t_bitmap, 0, h + spacing, paint);
        // 線性渲染-沿Y軸高到低渲染
        Shader shader = new LinearGradient(0, h + spacing, 0, h + spacing + h / 2, 0x70ffffff, 0x00ffffff, Shader.TileMode.MIRROR);
        paint.setShader(shader);
        // 取兩層繪制交集,顯示下層。
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
        // 繪制渲染倒影的矩形
        canvas.drawRect(0, h + spacing, w, h + h / 2 + spacing, paint);
        return bitmap;
    }


    /**
     * 獨立的倒影圖像
     * @param src
     * @return
     */
    public static Bitmap createReflectionBitmapForSingle(Bitmap src) {
        final int w = src.getWidth();
        final int h = src.getHeight();
        // 繪制高質量32位圖
        Bitmap bitmap = Bitmap.createBitmap(w, h / 2, Config.ARGB_8888);
        // 創建沿X軸的倒影圖像
        Matrix m = new Matrix();
        m.setScale(1, -1);
        Bitmap t_bitmap = Bitmap.createBitmap(src, 0, h / 2, w, h / 2, m, true);

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        // 繪制倒影圖像
        canvas.drawBitmap(t_bitmap, 0, 0, paint);
        // 線性渲染-沿Y軸高到低渲染
        Shader shader = new LinearGradient(0, 0, 0, h / 2, 0x70ffffff,
                0x00ffffff, Shader.TileMode.MIRROR);
        paint.setShader(shader);
        // 取兩層繪制交集。顯示下層。
        paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
        // 繪制渲染倒影的矩形
        canvas.drawRect(0, 0, w, h / 2, paint);
        return bitmap;
    }


    public static Bitmap createGreyBitmap(Bitmap src) {
        final int w = src.getWidth();
        final int h = src.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        // 顏色變換的矩陣
        ColorMatrix matrix = new ColorMatrix();
        // saturation 飽和度值,最小可設為0,此時對應的是灰度圖;為1表示飽和度不變,設置大於1,就顯示過飽和
        matrix.setSaturation(0);
        ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
        paint.setColorFilter(filter);
        canvas.drawBitmap(src, 0, 0, paint);
        return bitmap;
    }

    /**
     * 保存圖片
     * @param src
     * @param filepath
     * @param format:[Bitmap.CompressFormat.PNG,Bitmap.CompressFormat.JPEG]
     * @return
     */
    public static boolean saveImage(Bitmap src, String filepath, CompressFormat format) {
        boolean rs = false;
        File file = new File(filepath);
        try {
            FileOutputStream out = new FileOutputStream(file);
            if(src.compress(format, 100, out)) {
                out.flush();	//寫入流
            }
            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rs;
    }

    /**
     * 添加水印效果
     * @param src		源位圖
     * @param watermark	水印
     * @param direction	方向
     * @param spacing 間距
     * @return
     */
    public static Bitmap createWatermark(Bitmap src, Bitmap watermark, int direction, int spacing) {
        final int w = src.getWidth();
        final int h = src.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(src, 0, 0, null);
        if(direction == LEFT_TOP) {
            canvas.drawBitmap(watermark, spacing, spacing, null);
        } else if(direction == LEFT_BOTTOM){
            canvas.drawBitmap(watermark, spacing, h - watermark.getHeight() - spacing, null);
        } else if(direction == RIGHT_TOP) {
            canvas.drawBitmap(watermark, w - watermark.getWidth() - spacing, spacing, null);
        } else if(direction == RIGHT_BOTTOM) {
            canvas.drawBitmap(watermark, w - watermark.getWidth() - spacing, h - watermark.getHeight() - spacing, null);
        }
        return bitmap;
    }


    /**
     * 合成圖像
     * @param direction
     * @param bitmaps
     * @return
     */
    public static Bitmap composeBitmap(int direction, Bitmap... bitmaps) {
        if(bitmaps.length < 2) {
            return null;
        }
        Bitmap firstBitmap = bitmaps[0];
        for (int i = 0; i < bitmaps.length; i++) {
            firstBitmap = composeBitmap(firstBitmap, bitmaps[i], direction);
        }
        return firstBitmap;
    }

    /**
     * 合成兩張圖像
     * @param firstBitmap
     * @param secondBitmap
     * @param direction
     * @return
     */
    private static Bitmap composeBitmap(Bitmap firstBitmap, Bitmap secondBitmap,
                                        int direction) {
        if(firstBitmap == null) {
            return null;
        }
        if(secondBitmap == null) {
            return firstBitmap;
        }
        final int fw = firstBitmap.getWidth();
        final int fh = firstBitmap.getHeight();
        final int sw = secondBitmap.getWidth();
        final int sh = secondBitmap.getHeight();
        Bitmap bitmap = null;
        Canvas canvas = null;
        if(direction == TOP) {
            bitmap = Bitmap.createBitmap(sw > fw ? sw : fw, fh + sh, Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            canvas.drawBitmap(secondBitmap, 0, 0, null);
            canvas.drawBitmap(firstBitmap, 0, sh, null);
        } else if(direction == BOTTOM) {
            bitmap = Bitmap.createBitmap(fw > sw ? fw : sw, fh + sh, Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            canvas.drawBitmap(firstBitmap, 0, 0, null);
            canvas.drawBitmap(secondBitmap, 0, fh, null);
        } else if(direction == LEFT) {
            bitmap = Bitmap.createBitmap(fw + sw, sh > fh ? sh : fh, Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            canvas.drawBitmap(secondBitmap, 0, 0, null);
            canvas.drawBitmap(firstBitmap, sw, 0, null);
        } else if(direction == RIGHT) {
            bitmap = Bitmap.createBitmap(fw + sw, fh > sh ? fh : sh,
                    Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            canvas.drawBitmap(firstBitmap, 0, 0, null);
            canvas.drawBitmap(secondBitmap, fw, 0, null);
        }
        return bitmap;
    }


}

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