多勾配形状


177

次の画像のような形状を作成します。

代替テキスト

上半分の色1から色2へのグラデーションに注意してください。下半分の色3から色4へのグラデーションに注意してください。単一のグラデーションで図形を作成する方法は知っていますが、図形を分割する方法がわかりません2つの半分を作成し、2つの異なるグラデーションで1つの形状を作成します。

何か案は?


回答:


383

私はあなたがこれをXMLで(少なくともAndroidでは)実行できないと思いますが、ここに投稿された優れた解決策のように見える良い解決策を見つけました!

ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
    @Override
    public Shader resize(int width, int height) {
        LinearGradient lg = new LinearGradient(0, 0, width, height,
            new int[]{Color.GREEN, Color.GREEN, Color.WHITE, Color.WHITE},
            new float[]{0,0.5f,.55f,1}, Shader.TileMode.REPEAT);
        return lg;
    }
};

PaintDrawable p=new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);

基本的に、int配列では複数のカラーストップを選択でき、次のfloat配列はそれらのストップが配置される場所(0から1)を定義します。その後、前述のように、これを標準のDrawableとして使用できます。

編集:シナリオでこれを使用する方法は次のとおりです。次のようにXMLで定義されたボタンがあるとします。

<Button
    android:id="@+id/thebutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Press Me!"
    />

次に、onCreate()メソッドに次のようなものを配置します。

Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
    @Override
    public Shader resize(int width, int height) {
        LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
            new int[] { 
                Color.LIGHT_GREEN, 
                Color.WHITE, 
                Color.MID_GREEN, 
                Color.DARK_GREEN }, //substitute the correct colors for these
            new float[] {
                0, 0.45f, 0.55f, 1 },
            Shader.TileMode.REPEAT);
         return lg;
    }
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackground((Drawable)p);

現在、これをテストすることはできません。これは私の頭からのコードですが、基本的には、必要な色に置き換えたり、ストップを追加したりするだけです。基本的に、私の例では、ライトグリーンから始めて、中心より少し前に白にフェードし(過酷な遷移ではなくフェードを与えるため)、白からミッドグリーンに45%から55%の間でフェードし、次に中間の緑から濃い緑まで55%から最後まで。これはあなたの形と正確に同じではないかもしれませんが(今のところ、私はこれらの色をテストする方法がありません)、これを変更して例を複製することができます。

編集:また、0, 0, 0, theButton.getHeight()はグラデーションのx0、y0、x1、y1座標を参照します。したがって、基本的には、x = 0(左側)、y = 0(上)から始まり、x = 0まで伸びます(垂直方向のグラデーションが必要なので、左から右への角度は必要ありません)、y =高さボタンの。したがって、グラデーションはボタンの上部からボタンの下部まで90度の角度で進みます。

編集:さて、私はうまくいくもう一つのアイデアを持っています、ハハ。現在はXMLで動作しますが、Javaの形状でも実行できるはずです。それは一種の複雑で、それを単一の形状に単純化する方法があると思いますが、これは私が今持っているものです:

green_horizo​​ntal_gradient.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <corners
        android:radius="3dp"
        />
    <gradient
        android:angle="0"
        android:startColor="#FF63a34a"
        android:endColor="#FF477b36"
        android:type="linear"
        />    
</shape>

half_overlay.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >
    <solid
        android:color="#40000000"
        />
</shape>

layer_list.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item
        android:drawable="@drawable/green_horizontal_gradient"
        android:id="@+id/green_gradient"
        />
    <item
        android:drawable="@drawable/half_overlay"
        android:id="@+id/half_overlay"
        android:top="50dp"
        />
</layer-list>

test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    >
    <TextView
        android:id="@+id/image_test"
        android:background="@drawable/layer_list"
        android:layout_width="fill_parent"
        android:layout_height="100dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:text="Layer List Drawable!"
        android:textColor="@android:color/white"
        android:textStyle="bold"
        android:textSize="26sp"     
        />
</RelativeLayout>

わかりましたので、基本的には、XMLで、上部の領域の左の緑色から右の緑色に向かって0度の角度で設定された水平の緑のグラデーションの形状グラデーションを作成しました。次に、半透明の灰色の長方形を作りました。レイヤーリストのXMLにインライン化して、この余分なファイルを取り除くことができると確信していますが、方法はわかりません。しかし、わかりました。このようなハックな部分は、layer_list XMLファイルに含まれています。緑のグラデーションを下のレイヤーとして配置し、次に半分のオーバーレイを2番目のレイヤーとして、上から50 dpオフセットします。もちろん、この数は常にビューサイズの半分であり、固定の50 dpではありません。ただし、パーセンテージは使用できないと思います。そこから、layer_list.xmlファイルを背景として使用して、TextViewをtest.xmlレイアウトに挿入しました。

代替テキスト

多田!

もう1つ編集:図形を項目として描画可能なレイヤーリストに埋め込むだけでよいことに気づきました。つまり、3つの個別のXMLファイルはもう必要ありません。次のようにそれらを組み合わせて同じ結果を得ることができます:

layer_list.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <item>
        <shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle"
            >
            <corners
                android:radius="3dp"
                />
            <gradient
                android:angle="0"
                android:startColor="#FF63a34a"
                android:endColor="#FF477b36"
                android:type="linear"
                />    
        </shape>
    </item>
    <item
        android:top="50dp" 
        >
        <shape
            android:shape="rectangle"
            >
            <solid
                android:color="#40000000"
                />
        </shape>            
    </item>
</layer-list>

このように好きなだけアイテムを重ねることができます!私は遊んでみて、Javaを介してより用途の広い結果が得られるかどうかを確認するかもしれません。

これが最後の編集だと思います...:わかりました。次のように、Javaを使用して位置を確実に修正できます。

    TextView tv = (TextView)findViewById(R.id.image_test);
    LayerDrawable ld = (LayerDrawable)tv.getBackground();
    int topInset = tv.getHeight() / 2 ; //does not work!
    ld.setLayerInset(1, 0, topInset, 0, 0);
    tv.setBackgroundDrawable(ld);

しかしながら!これは、描画が完了するまでTextViewを測定できないという別の厄介な問題につながります。どうすればこれを達成できるのかはまだよくわかりませんが、topInsetに手動で数値を挿入しても機能します。

私は嘘をついた、もう1つの編集

わかりまし。コンテナの高さに合わせてこのドローアブルを手動で更新する方法を見つけまし。詳しい説明はこちらにあります。このコードは、onCreate()メソッドに追加する必要があります。

final TextView tv = (TextView)findViewById(R.id.image_test);
        ViewTreeObserver vto = tv.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                LayerDrawable ld = (LayerDrawable)tv.getBackground();
                ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
            }
        });

これで完了です。ふew!:)


これの問題は、グラデーションが垂直であることです。形状を垂直に分離する必要があります(つまり:水平線)が、グラデーションを水平にする必要があります(つまり、左から右に移動します)。この例では、セパレータとグラデーションの両方が垂直です。
Andrew

わかりました、今あなたの言っていることがわかります。(画像は仕事でブロックされているので、私は私の携帯電話からしかあなたの画像を見ることができず、詳細をはっきりと伝えることはできません)残念ながら私はその手先には解決策がありませんが、2つの長方形で描画可能な図形を作成できると思いますが、1つは水平方向のグラデーション、もう1つは白から黒の垂直方向のグラデーションで、半分のサイズで半分の不透明度で、下に揃えます。その方法については、現時点では具体的な例はありません。
Kevin Coppock

ええ、それが私ができることを望んでいたことですが、私はまだそれを理解していません。私はあなたの助けに感謝します
Andrew

どういたしまして!もう一度試してみましたが、あなたが探しているものはほとんど手に入れたと思います。Javaを介してこれらを動的に作成する必要がある場合があります(コメントに従って)が、これは現在、固定サイズのトリックです。
ケビンコポック2010

17
それはあなたが少なくとも+10に与えたい種類の答えです。私はあなたの答えの戦いの感覚が大好きです:あなたはAndroid API対誰が勝つでしょうか?知っているだろうか?;)加えて、あなたが遭遇したすべての癖を保持したので、それは非常に便利な学習教材です。
2013年

28

レイヤーリストを使用して、グラデーションの形状をxmlにレイヤー化できます。次のデフォルト状態のボタンを想像してください。2番目の項目は半透明です。ケラレのようなものを追加します。(カスタム定義の色はお許しください。)

<!-- Normal state. -->
<item>
    <layer-list>
        <item>  
            <shape>
                <gradient 
                    android:startColor="@color/grey_light"
                    android:endColor="@color/grey_dark"
                    android:type="linear"
                    android:angle="270"
                    android:centerColor="@color/grey_mediumtodark" />
                <stroke
                    android:width="1dp"
                    android:color="@color/grey_dark" />
                <corners
                    android:radius="5dp" />
            </shape>
        </item>
        <item>  
            <shape>
                <gradient 
                    android:startColor="#00666666"
                    android:endColor="#77666666"
                    android:type="radial"
                    android:gradientRadius="200"
                    android:centerColor="#00666666"
                    android:centerX="0.5"
                    android:centerY="0" />
                <stroke
                    android:width="1dp"
                    android:color="@color/grey_dark" />
                <corners
                    android:radius="5dp" />
            </shape>
        </item>
    </layer-list>
</item>


4

xmlシェイプのみを使用してそれを行うことができます-次のようにレイヤーリストと負のパディングを使用するだけです:

    <layer-list>

        <item>
            <shape>
                <solid android:color="#ffffff" />

                <padding android:top="20dp" />
            </shape>
        </item>

        <item>
            <shape>
                <gradient android:endColor="#ffffff" android:startColor="#efefef" android:type="linear" android:angle="90" />

                <padding android:top="-20dp" />
            </shape>
        </item>

    </layer-list>

1

この方法を試してみると、あなたが望むすべてのことを行うことができます。
それは次のようである、スタックので、最初か最後になるどの項目に注意してください。

<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="50dp" android:start="10dp" android:left="10dp">
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <corners android:radius="3dp" />
        <solid android:color="#012d08"/>
    </shape>
</item>
<item android:top="50dp">
    <shape android:shape="rectangle">
        <solid android:color="#7c4b4b" />
    </shape>
</item>
<item android:top="90dp" android:end="60dp">
    <shape android:shape="rectangle">
        <solid android:color="#e2cc2626" />
    </shape>
</item>
<item android:start="50dp" android:bottom="20dp" android:top="120dp">
    <shape android:shape="rectangle">
        <solid android:color="#360e0e" />
    </shape>
</item>


0

緑のグラデーションの不透明な不透明度を持つ別の画像の上に、ハイライトの透明度がほぼ不透明なグラデーションをオーバーレイしようとしましたか?


いいえ、ありません。ただし、あるグラデーションを別のグラデーションの上に配置する方法はよくわかりません。私は形状をandroid:background = "@ drawable / myshape"を使用してLinearLayoutの背景として使用しています
Andrew

不透明度が異なる2つの形状を互いに重ねることはできますか?(わかりません。)
Greg D
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.