[Android] 外部ストレージに配置した複数の画像を状態付きで設定する

| トラックバック(0) |

先日のエントリ「通知アイテムの背景画像を差し替える」は、

ビルド時に画像が固定で埋め込まれているため、画像の差し替えが大変だけでなく、

ビルドできる人しか画像を差し替えることができない、という問題がありました^^;

 

そこで、外部ストレージに配置した複数の画像を状態付きで設定するコードを作成し、検証してみたところ、

問題なく動作することを確認できました。

※「画像を状態別に設定できる」かつ「1つの View に複数の画像を設定できる」という点がポイントです

 

この方法を使用することで、カスタム ROM の画像リソースを、外部ファイル化することができそうです^^

※見ろ!先日のエントリのリソースのハードコードがゴミのようだ!

 

以下、解説です。

 

外部ストレージから読み込んだ画像を設定するには(Step1)

外部ストレージにある画像を Drawable#createFromPath(String) を使用して作成し、

画像を設定したい View に対し View#setBackgroundDrawable(Drawable) を呼び出します。

ここまでで、外部ストレージにある画像を、任意の View に適用できます。

 

外部ストレージから読み込んだ画像を状態付きで設定するには(Step2)

Step1 に加え、画像を「通常状態」「押下状態」など、状態付きで設定してみます。

通常、画像を状態付きで設定するには、<selector> を記述した xml リソースファイルを指定しますが、

ここでは、ソースコードから動的に作成してみます。

まず、 StateListDrawable インスタンスを作成し、

次に、追加したい状態を StateListDrawable#addState(int[], Drawable) を使用して追加し、

画像を設定したい View に対し View#setBackgroundDrawable(Drawable) を呼び出します。

ここまでで、外部ストレージにある画像を「状態付き」で、任意の View に適用できます。

 

外部ストレージから読み込んだ複数の画像を状態付きで設定するには(Step3)

Step2 に加え、複数の画像(画像00、画像01、・・・)を設定してみます。

通常、複数の画像を設定するには、<level-list> を記述した xml リソースファイルを指定しますが、

ここでは、ソースコードから動的に作成してみます。

まず、LevelListDrawable インスタンスを作成し、

次に、追加したい画像を LevelListDrawable#addLevel(int, int, Drawable) を使用して追加し、

画像を設定したい View に対し View#setBackgroundDrawable(Drawable) を呼び出します。

追加した任意の画像に切り替えるには、Drawable#setLevel((int) を呼び出します。

これで、外部ストレージにある「複数」の画像を「状態付き」で、任意の View に適用できます。

 

以下、ソースコードサンプルです。

※サンプルのためエラー処理などは省略しています

 

ソースコード

  • src / StateTestActivity.java
package com.adakoda.android.statetest;
import java.io.File;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LevelListDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Bundle;
import android.os.Environment;
import android.util.StateSet;
import android.view.View;
import android.widget.ImageView;
import com.adakoda.android.statetest.R.id;
public class StateTestActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        step1Sample();
//        step2Sample();
//        step3Sample();
    }
    // ------------------------------------------------------------------
    // Step1
    // 実行するには、SDカード直下に"image.png"を置いてください
    // ------------------------------------------------------------------
    private static String STEP1_IMAGE_FILENAME = "image.png";
    private void step1Sample() {
        // ファイルパス文字列作成(例:"/mnt/sdcard/image.png")
        StringBuilder builder = new StringBuilder();
        builder.append(Environment.getExternalStorageDirectory().toString());
        builder.append(File.separator);
        builder.append(STEP1_IMAGE_FILENAME);
        String filePath = builder.toString();
        // 指定したパスからDrawableを作成
        Drawable drawable = Drawable.createFromPath(filePath);
        final ImageView imageView = (ImageView) findViewById(id.imageview);
        imageView.setBackgroundDrawable(drawable);
    }
    // ------------------------------------------------------------------
    // Step2
    // 実行するには、SDカード直下に
    // "image_normal.png"、"image_pressed.png"、
    // を置いてください。
    // 画像を押下すると、イメージが切り替わります。
    // ------------------------------------------------------------------
    private static String STEP2_STATE_FILENAME_FORMAT = "image_%s.png";
    private static String STEP2_STATE_FILENAME_SUFFIX_NORMAL = "normal";
    private static String STEP2_STATE_FILENAME_SUFFIX_PRESSED = "pressed";
    private void step2Sample() {
        // ファイルパス文字列のフォーマット文字列作成(例:"/mnt/sdcard/image_%s.png")
        StringBuilder builder = new StringBuilder();
        builder.append(Environment.getExternalStorageDirectory().toString());
        builder.append(File.separator);
        builder.append(STEP2_STATE_FILENAME_FORMAT);
        String filePathFormat = builder.toString();
        // StateListDrawable作成
        StateListDrawable stateListDrawable = new StateListDrawable();
        {
            // 押下状態のDrawable作成
            {
                // 例:"/mnt/sdcard/image_pressed.png"
                String pathPressed = String.format(filePathFormat,
                        STEP2_STATE_FILENAME_SUFFIX_PRESSED);
                Drawable drawablePressed = Drawable.createFromPath(pathPressed);
                stateListDrawable.addState(
                        new int[] { android.R.attr.state_pressed },
                        drawablePressed);
            }
            // 通常の状態のDrawable作成
            {
                // 例:"/mnt/sdcard/image_normal.png"
                String pathNormal = String.format(filePathFormat,
                        STEP2_STATE_FILENAME_SUFFIX_NORMAL);
                Drawable drawableNormal = Drawable.createFromPath(pathNormal);
                stateListDrawable.addState(StateSet.WILD_CARD, drawableNormal);
            }
        }
        // 動的に作成したStateListDrawableを背景画像に設定
        final ImageView imageView = (ImageView) findViewById(id.imageview);
        imageView.setBackgroundDrawable(stateListDrawable);
    }
    // ------------------------------------------------------------------
    // Step3
    // 実行するには、SDカード直下に
    // "image_00_normal.png"、"image_00_pressed.png"、
    // "image_01_normal.png"、"image_01_pressed.png"、
    // を置いてください。
    // 画像を押下すると、イメージが切り替わります。
    // ------------------------------------------------------------------
    private static final int STEP3_FILE_NUM = 2; // とりあえず
    private static String STEP3_STATE_FILENAME_FORMAT = "image_%02d_%s.png";
    private static String STEP3_STATE_FILENAME_SUFFIX_NORMAL = "normal";
    private static String STEP3_STATE_FILENAME_SUFFIX_PRESSED = "pressed";
    private void step3Sample() {
        // ファイルパス文字列のフォーマット文字列作成( 例:"/mnt/sdcard/image_%02d_%s.png")
        StringBuilder builder = new StringBuilder();
        builder.append(Environment.getExternalStorageDirectory().toString());
        builder.append(File.separator);
        builder.append(STEP3_STATE_FILENAME_FORMAT);
        String filePathFormat = builder.toString();
        // LevelListDrawable作成
        final LevelListDrawable levelListDrawable = new LevelListDrawable();
        for (int i = 0; i < STEP3_FILE_NUM; i++) {
            // StateListDrawable作成
            StateListDrawable stateListDrawable = new StateListDrawable();
            {
                // 押下状態のDrawable作成
                {
                    // 例:"/mnt/sdcard/image_00_pressed.png"
                    String pathPressed = String.format(filePathFormat, i,
                            STEP3_STATE_FILENAME_SUFFIX_PRESSED);
                    Drawable drawablePressed = Drawable
                            .createFromPath(pathPressed);
                    stateListDrawable.addState(
                            new int[] { android.R.attr.state_pressed },
                            drawablePressed);
                }
                // 通常の状態のDrawable作成
                {
                    // 例:"/mnt/sdcard/image_00_normal.png"
                    String pathNormal = String.format(filePathFormat, i,
                            STEP3_STATE_FILENAME_SUFFIX_NORMAL);
                    Drawable drawableNormal = Drawable
                            .createFromPath(pathNormal);
                    stateListDrawable.addState(StateSet.WILD_CARD,
                            drawableNormal);
                }
            }
            // LevelListDrawableのn番目に作成したStateListDrawableを追加
            levelListDrawable.addLevel(i, i, stateListDrawable);
        }
        // 動的に作成したLevelListDrawableを背景画像に設定
        final ImageView imageView = (ImageView) findViewById(id.imageview);
        imageView.setBackgroundDrawable(levelListDrawable);
        // 初期状態として0番目のStatListDrawableを設定
        levelListDrawable.setLevel(0);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 押下時、次のStatListDrawableに切り替える
                int newLevel = (levelListDrawable.getLevel() + 1)
                        % STEP3_FILE_NUM;
                levelListDrawable.setLevel(newLevel);
            }
        });
    }
}

 

リソース

  • res / layout / main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <ImageView
        android:id="@+id/imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true" />
</LinearLayout>

トラックバック(0)

トラックバックURL: http://mt.adakoda.com/mt-tb.cgi/567

2016年8月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31