Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 音樂播放器(八)桌面小工具(上)

音樂播放器(八)桌面小工具(上)

編輯:關於Android編程

第8節 桌面小工具

桌面小工具是可以放置在主界面的、快速控制應用的小助手。例如我們的音樂小工具,它可以幫助用戶在桌面上就完成音樂的暫停、播放、切換等操作,而不需要啟動應用本身。

在安卓系統中,我們也常常叫它App widget。

\

實現一個App widget要經過以下幾個步驟,

創建一個App widget類,讓它繼承自AppWidgetProvider,例如AnddleMusicAppWidget類; 放在res\layout目錄下,為App widget的界面定義一個布局,例如anddle_music_app_widget.xml; 在res\xml目錄下,定義一個App widget的說明文件,例如anddle_music_app_widget_info.xml 在AndroidManifest.xml文件當中,聲明App widget;

8.1 小工具框架的創建

對於使用Android Studio的用戶來說,完成上面四個步驟的方法非常簡單。因為Android Studio提供了簡單的可視化向導來幫助我們。

在項目工程上點擊右鍵,選擇new->Wideget->App Widget就為我們創建好了開發用的模版,非常的簡單方便。

\

在彈出的創建向導中,填上創建的參數,

\ 給App widget取個名字-AnddleMusicAppWidget; 允許將App widget放到主界面上; 不允許App widget的顯示區域動態調整; App widget占用3格寬1格高;

這些參數最後將反應在res/xml/anddle_music_app_widget.info.xml這個配置文件當中,


運行起來,就可以開始將App widget添加到桌面了。

8.2 界面設計

現在,我們開始修改布局文件anddle_music_app_widget.xml,將App widget設計成如下的效果,

\


    

    

        

        

然後修改anddle_music_app_widget_info.xml的android:previewImage屬性,讓它指向的圖片變成預覽的效果圖,


\

8.3 AnddleMusicAppWidget的重建

AnddleMusicAppWidget類負責App widget的邏輯響應。

8.3.1 AppWidget原理

繼承AppWidgetProvider之後,開發者可以選擇的實現onUpdate() onAppWidgetOptionsChanged() onDeleted() onEnabled() onDisabled()和onRestored()等多個函數,

public class AnddleMusicAppWidget extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

    }

    @Override
    public void onEnabled(Context context) {

    }

    @Override
    public void onDisabled(Context context) {

    }

    @Override
    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
            int appWidgetId, Bundle newOptions) {

    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {

    }

    @Override
    public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {

    }

}

桌面上可以同時添加多個相同的App widget,系統會為每個App widget分配一個id,以便將來更新它們或者對它們進行別的操作時,能夠正確的區分它們。

假設現在桌面上沒有我們音樂播放器對應的App widget,此時添加一個的話,會依次觸發,

onEnabled()
onUpdate()

如果此時繼續添加,會接著觸發,

onUpdate()

如果系統要更新App widget的顯示,也會觸發,

onUpdate()

此時刪除一個,會觸發,

onDeleted()

此時再刪除最後一個,會觸發,

onDeleted()
onDisabled()

當設備開機,會觸發,

onEnabled()
onUpdate()

在App widget的設計框架中,每個顯示出來的小工具界面,叫做RemoteViews,它是由如下方式創建的,

//第二個參數就是桌面小工具的布局文件
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);

然後由RemoteViews提供的設置方法,來設置界面上每個元素的樣子,比如某個TextView該顯示什麼文字,某個ImageView該顯示什麼圖片,某個Button被點擊後要觸發什麼操作等等。

然後,通過調用系統提供的AppWidgetManager.updateAppWidget(),將這個界面更新到App widget上面去,

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
//appWidgetId就是主界面上某個特定App widget的Id值,它會由onUpdate()函數傳入
appWidgetManager.updateAppWidget(appWidgetId, views);

所以AnddleMusicAppWidget要提供一個對外調用的接口,讓其它組件可以在需要的時候更新小工具界面。

8.3.2 App widget的界面元素

前面提到了RemoteViews的創建方法。現在來詳細介紹下界面上每個元素的設置方式,比如某個TextView該顯示什麼文字,某個ImageView該顯示什麼圖片,某個Button被點擊後要觸發什麼操作等等。

8.3.2.1 設置TextView的文字

如果創建RemoteViews的布局中有TextView控件,並需要設置內容,

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);
//設置id為R.id.music_name的TextView,顯示musicName代表的字符串
views.setTextViewText(R.id.music_name, musicName);

8.3.2.2 設置ImageView的背景圖片

如果創建RemoteViews的布局中有ImageView控件,並需要設置圖片內容,

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);
//設置id為R.id.image_thumb的ImageView,顯示thumb代表的bitmap圖片
views.setImageViewBitmap(R.id.image_thumb, thumb);

8.3.2.3 控件的其它屬性

除了上面提到的控件和屬性,控件的很多屬性並專門的設置函數。不過RemoteViews為我們引入了更加靈活的設置方式。例如要設置Button的background屬性,

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);
//設置id為R.id.image_thumb的Button,調用它的setBackgroundResource()函數,
//傳入R.mipmap.ic_pause參數,相當於調用了Button的setBackgroundResource(R.mipmap.ic_pause)
views.setInt(R.id.play_btn2, "setBackgroundResource", R.mipmap.ic_pause);

8.3.2.4 Button的響應

如果創建RemoteViews的布局中有Button控件,為它添加點擊響應,

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);

//用隱士調用的方法-指定Action-創建一個Intent
Intent preIntent = new Intent(MusicService.ACTION_PLAY_MUSIC_PRE);
//設置響應的組件名稱
preIntent.setComponent(serviceName);
//將Intent轉化成PendingIntent
PendingIntent prePendingIntent = PendingIntent.getService(context,
                0, preIntent, 0);
//設置id為R.id.pre_btn2的Button,設計點擊後要觸發的PendingIntent
views.setOnClickPendingIntent(R.id.pre_btn2, prePendingIntent);

RemoteViews不能直接設置按鈕點擊後的操作,必須通過設置PendingIntent來實現。所以要在響應的模塊中添加響應的邏輯。

8.3.3 AnddleMusicAppWidget實現

繼承AppWidgetProvider,准備實現onUpdate()函數,並提供performUpdates()的靜態函數作為其它組件刷新界面的接口,搭建的代碼結構如下,

public class AnddleMusicAppWidget extends AppWidgetProvider {

    //保存各個小工具的id
    private static int [] sAppWidgetIds;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        //保存各個小工具的id,以備將來其它組件調用performUpdates()接口時能用到
        sAppWidgetIds = appWidgetIds;
        //更新小工具的界面
        performUpdates(context, context.getString(R.string.no_song), false, null);
    }

    //對外提供的更新所有小工具的界面接口,需要傳入音樂的名稱、當前是否播放、音樂封面等參數
    public static void performUpdates(Context context, String musicName, boolean isPlaying, Bitmap thumb) {
        //如果沒有小工具的id,就沒法更新界面
        if(sAppWidgetIds == null || sAppWidgetIds.length == 0) {

            return;
        }

        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

        //遍歷每個桌面上的小工具,根據id逐個更新界面
        for (int appWidgetId : sAppWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId, musicName, isPlaying, thumb);
        }
    }

    //更新指定id的小工具界面
    private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                                int appWidgetId, String musicName, boolean isPlaying, Bitmap thumb) {

        //創建RemoteViews
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);

        //添加界面元素的邏輯控制代碼,例如按鈕、文字、圖片等等
        ......

        //通過appWidgetId,為指定的小工具界面更新
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
    ......
}

實現對界面元素的邏輯控制,

“`java
public class AnddleMusicAppWidget extends AppWidgetProvider {

......

//更新指定id的小工具界面
private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId, String musicName, boolean isPlaying, Bitmap thumb) {

    //創建RemoteViews
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.anddle_music_app_widget);

    //添加界面元素的邏輯控制代碼,例如按鈕、文字、圖片等等
    //設置音樂的名稱
    views.setTextViewText(R.id.music_name, musicName);

    //設置按鈕響應的對象,這裡是MusicService
    final ComponentName serviceName = new ComponentName(context, MusicService.class);

    //設置下一首按鈕對應的PendingIntent
    //通過MusicService.ACTION_PLAY_MUSIC_NEXT定義隱性Intent,喚醒MusicService的響應
    Intent nextIntent = new Intent(MusicService.ACTION_PLAY_MUSIC_NEXT);
    nextIntent.setComponent(serviceName);
    PendingIntent nextPendingIntent = PendingIntent.getService(context,
            0, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    views.setOnClickPendingIntent(R.id.next_btn2, nextPendingIntent);

    //設置前一首按鈕對應的PendingIntent
    //通過MusicService.ACTION_PLAY_MUSIC_PRE定義隱性Intent,喚醒MusicService的響應
    Intent preIntent = new Intent(MusicService.ACTION_PLAY_MUSIC_PRE);
    preIntent.setComponent(serviceName);
    PendingIntent prePendingIntent = PendingIntent.getService(context,
            0, preIntent, 0);
    views.setOnClickPendingIntent(R.id.pre_btn2, prePendingIntent);

    //設置播放暫停按鈕對應的PendingIntent
    //通過MusicService.ACTION_PLAY_MUSIC_TOGGLE定義隱性Intent,喚醒MusicService的響應
    Intent toggleIntent = new Intent(MusicService.ACTION_PLAY_MUSIC_TOGGLE);
    toggleIntent.setComponent(serviceName);
    PendingIntent togglePendingIntent = PendingIntent.getService(context,
            0, toggleIntent, 0);
    views.setOnClickPendingIntent(R.id.play_btn2, togglePendingIntent);

    //設置播放暫停按鈕的圖標
    views.setInt(R.id.play_btn2, "setBackgroundResource", isPlaying ? R.mipmap.ic_pause : R.mipmap.ic_play);
    //設置音樂的封面
    if(thumb != null) {
        views.setImageViewBitmap(R.id.image_thumb, thumb);
    }
    else {
        views.setImageViewResource(R.id.image_thumb, R.mipmap.default_cover);
    }

    //通過appWidgetId,為指定的小工具界面更新
    appWidgetManager.updateAppWidget(appWidgetId, views);
}
......

}

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