180

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

代替テキスト

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

何か案は?

4

5 に答える 5

386

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配列を使用すると、複数のカラーストップを選択できます。次のフロート配列は、それらのストップが配置される場所(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度の角度で進みます。

編集:さて、私はうまくいくもう1つのアイデアがあります、ハハ。現在は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>

さて、基本的には、上部の領域の左側の緑色から右側の緑色に向かって、0度の角度に設定された水平方向の緑色のグラデーションの形状グラデーションをXMLで作成しました。次に、半分透明な灰色の長方形を作りました。これをレイヤーリストXMLにインライン化して、この余分なファイルを不要にすることができると確信していますが、その方法はわかりません。しかし、それでは、この種のハッキーな部分がlayer_listXMLファイルに含まれます。緑のグラデーションを下のレイヤーとして配置し、次にハーフオーバーレイを2番目のレイヤーとして配置し、上から50dpオフセットします。もちろん、この数値は、固定の50dpではなく、ビューサイズの半分にする必要があります。ただし、パーセンテージは使用できないと思います。そこから、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);
            }
        });

そして、私は終わりました!ふぅ!:)

于 2010-12-07T20:22:31.800 に答える
29

レイヤーリストを使用して、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>

于 2012-08-12T15:29:53.097 に答える
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>
于 2014-06-24T13:32:07.700 に答える
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>

于 2017-11-02T17:08:11.953 に答える
0

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

于 2010-12-07T20:12:33.083 に答える