Android アプリ開発「MATRIX」

Androidアプリの開発に役立つサンプル集


タップすると画像が切り替わるウィジェットの作り方(APIレベル 27まで)

タップで画像が切り替わるウィジェット

今回はウィジェットをタップするとその中に配置してある ImageView の画像が切り替わるウィジェットを作ります。ホーム画面に配置されたウィジェットを変更する方法はいくつかありますが、今回はウィジェットが自分自身で内部の画像を切り替える方法を説明します。

(注意)この作成方法はAPIレベルが27まで使えます。

サンプルコード①(MainActivity.java)

ウィジェットはアクティビティを必要としませんので、MainActivity.java があっても使用することはありません。プロジェクト内に最初からある場合はそのまま放置してください。

サンプルコード②(MyWidget3.java)

今回のメインで唯一のJavaのプログラムコードになります。サンプルコードの詳しい説明はコード内のコメントを参照してください。

public class MyWidget3 extends AppWidgetProvider {

// ウィジェットをホーム画面に配置すると呼び出される
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);

// ウィジェットIDを取得(配列にあるの最初の値でOK
int myWidgetID = appWidgetIds[0];

// ウィジェットのレイアウトファイルにアクセスするための準備(レイアウトファイルの取得)
RemoteViews remoteViews1 = new RemoteViews(context.getPackageName(), R.layout.activity_main);
// インテントを生成してインスタンス化
Intent intent = new Intent();
// インテントにアクション名「CLICK_TEST」をセット
intent.setAction("CLICK_TEST");
// インテントにウィジェットIDを追加
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, myWidgetID);
// ウィジェットIDとインテントをブロードキャストするペンディングインテントを生成
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, myWidgetID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// imageView」をクリックした時にペンディングインテントを実行できるようにする
remoteViews1.setOnClickPendingIntent(R.id.imageView, pendingIntent1);
// ウィジェットを更新する
appWidgetManager.updateAppWidget(myWidgetID, remoteViews1);
}

// ブロードキャストを受信すると呼び出される
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);

// CLICK_TEST」というアクション名だけに反応させる
if (intent.getAction().equals("CLICK_TEST")) {

// 押されたウィジェットIDをインテントから取得
int changeWidgetID = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID);
// ウィジェットのレイアウトファイルにアクセスするための準備(レイアウトファイルの取得)
RemoteViews remoteViews2 = new RemoteViews(context.getPackageName(), R.layout.activity_main);
// レイアウトファイル内にある「imageView」の画像を「pslogo」に差し替える
remoteViews2.setImageViewResource(R.id.imageView, R.drawable.pslogo);
// ウィジェットマネージャーを取得
AppWidgetManager widgetManager1 = AppWidgetManager.getInstance(context);
// ウィジェットを更新する
widgetManager1.updateAppWidget(changeWidgetID, remoteViews2);
}
}

@Override
public void onDisabled(Context context) {
super.onDisabled(context);
// 必要に応じて記述
}

@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
// 必要に応じて記述
}

@Override
public void onEnabled(Context context) {
super.onEnabled(context);
// 必要に応じて記述
}

@Override
public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
super.onRestored(context, oldWidgetIds, newWidgetIds);
// 必要に応じて記述
}
}

 

サンプルコード③(AndroidManifest.xml)

マニフェストファイルにはウィジェットのレシーバーを登録して、「CLICK_TEST」というアクション名のインテントフィルターを追記します。これを忘れるとウィジェットが正しく動きませんので注意してください。

それから、ウィジェットの情報ファイル「my_app_widget_info.xml」の登録も忘れずに行ってください。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="matrix.sample.co.jp.widgettest2019">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<receiver android:name=".MyWidget3">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<!-- CLICK_TEST」というアクション名のインテントも受信する設定 -->
<action android:name="CLICK_TEST" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>

</application>
</manifest>

サンプルコード④(activity_main.xml)

レイアウトファイルは画面の中央に ImageView を1個配置しただけの簡単なものです。ウィジェットのレイアウトは中央以外にも左寄せ、右寄せにすることもできますが、ホーム画面に配置した時に左右に寄ってしまうので、上下左右ともに中央寄せにした方が良いでしょう。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:src="@drawable/image" />
</RelativeLayout>

サンプルコード⑤(my_app_widget_info.xml)

このファイルは、使用するレイアウト、縦横の最小サイズ、リサイズの設定、更新時間、どこで使うウィジェットなのか、というのを設定するファイルです。

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/activity_main"
android:minHeight="40dp"
android:minWidth="40dp"
android:previewImage="@drawable/image"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen"></appwidget-provider>

実行結果

① 今回のウィジェットをホーム画面に配置すると縦横のリサイズができるシンプルな画像だけのウィジェットが表示されます。

アンドロイド開発「タッチに反応するウィジェットの作り方」①

② そのウィジェットをタップすると、ウィジェットの画像が別の画像に切り替わります。

アンドロイド開発「タッチに反応するウィジェットの作り方」②

③ 今度は同じウィジェットをホーム画面に複数(今回は6個)並べてみます。

アンドロイド開発「タッチに反応するウィジェットの作り方」③

④ 並べられたウィジェットを適当にタップすると、タップされたウィジェットの画像だけが別の画像に切り替わります。

アンドロイド開発「タッチに反応するウィジェットの作り方」④

備考・その他

通常、同じウィジェットを多数並べることはありませんが、この方法を利用すれば基本的に同じ機能を持ちながらも、微妙に違っているウィジェットを配置できるようになるので、工夫次第では便利なアプリを作ることができそうですね。

END