web-dev-qa-db-ja.com

プログラムで、ストロークを使用して円形のドローアブルを作成するにはどうすればよいですか?

バックグラウンド

特定の色と幅のストロークと内部の画像を含む、塗りつぶされた円を作成しようとしています。

これはXMLで簡単に実行できます(これは単なるサンプルです):

<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item>
        <shape Android:shape="oval">
            <size
                Android:width="120dp" Android:height="120dp"/>
            <solid Android:color="#ffff0000"/>
            <stroke
                Android:width="3dp" Android:color="#ff00ff00"/>
        </shape>
    </item>
    <item
        Android:width="60dp" Android:height="60dp" Android:drawable="@Android:drawable/btn_star"
        Android:gravity="center"/>
</layer-list>

enter image description here

問題

プログラムで変更するには、上記の特定のプロパティが必要なので、XMLファイルを使用できませんが、考え方は同じです。

XMLで行われているように、OvalShapeドローアブルにストロークを配置する簡単な方法を見つけることができません。それを行う機能が見つかりません。

私が試したこと

StackOverflowには解決策がありますが、うまく機能する解決策は見つかりませんでした。私が見つけたのは here だけですが、そのストロークラインはカットされています。

ただし、ストローク自体にXMLを使用することで、これを解決する1つの方法で部分的に成功しました。

stroke_drawable.xml

<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:shape="oval">
    <stroke
        Android:width="4dp" Android:color="@Android:color/white"/>
</shape>

コード:

    final int strokeDrawableResId = R.drawable.stroke_drawable;
    Drawable innerDrawable = ResourcesCompat.getDrawable(getResources(), ..., null);
    final Drawable strokeDrawable = ResourcesCompat.getDrawable(getResources(), strokeDrawableResId, null);
    ShapeDrawable biggerCircle = new ShapeDrawable(new OvalShape());
    int size = ...;
    biggerCircle.setIntrinsicHeight(size);
    biggerCircle.setIntrinsicWidth(size);
    biggerCircle.getPaint().setColor(0xffff0000);
    biggerCircle.setBounds(new Rect(0, 0, size, size));
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{biggerCircle, strokeDrawable, innerDrawable});

    ImageView imageView = findViewById(R.id.imageView);
    imageView.setImageDrawable(layerDrawable);

動作しますが、完全にプログラムではありません(ストロークはXMLで定義されています)。

質問

完全にプログラム可能なようにコードを変更するにはどうすればよいですか?


編集:ここで提案されていることを試しましたが、背景に追加のドローアブルを追加する代わりに、すべてを1つのドローアブルで必要としたため、LayerDrawableを使用しました。

    Drawable innerDrawable = ResourcesCompat.getDrawable(getResources(), Android.R.drawable.btn_star, null);
    int strokeWidth = 5;
    int strokeColor = Color.parseColor("#ff0000ff");
    int fillColor = Color.parseColor("#ffff0000");
    GradientDrawable Gd = new GradientDrawable();
    Gd.setColor(fillColor);
    Gd.setShape(GradientDrawable.OVAL);
    Gd.setStroke(strokeWidth, strokeColor);
    LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{Gd, innerDrawable});
    ImageView imageView = findViewById(R.id.imageView);
    imageView.setImageDrawable(layerDrawable);

これは機能しますが、何らかの理由で内部のドローアブル(星)が引き伸ばされています:

enter image description here

6

あなたはこれをプログラムで行うことができます
In YourActivity.XMl、通常どおりImageViewを設定します。

<ImageView
            Android:layout_width="100dp"
            Android:layout_height="100dp"
            Android:id="@+id/id1"
            Android:src="@mipmap/ic_launcher_round"                                
            Android:padding="15dp"/>

そしてあなたのMainActivity.Java

    ImageView iV = (ImageView) findViewById(R.id.id1);
    int strokeWidth = 5;
    int strokeColor = Color.parseColor("#03dc13");
    int fillColor = Color.parseColor("#ff0000");
    GradientDrawable Gd = new GradientDrawable();
    Gd.setColor(fillColor);
    Gd.setShape(GradientDrawable.OVAL);
    Gd.setStroke(strokeWidth, strokeColor);
    iV.setBackground(Gd);

setColorは背景色を設定し、setStrokeはストローク幅とストローク色を設定します。
理解しやすくするために、色、幅などのローカル変数をいくつか作成しました。
結果
enter image description here
パディングを増やすほど、円のサイズが大きくなります。

12
Lalit Fauzdar