[解決済み] マルチグラディエントシェイプ
質問
以下の画像のような形状を作りたいのですが、どうすればいいですか?
上半分は色1から色2へのグラデーション、下半分は色3から色4へのグラデーションであることに注意してください。 1つのグラデーションを持つシェイプを作る方法は知っていますが、シェイプを2つに分割し、2つの異なるグラデーションを持つ1つのシェイプを作る方法はわかりません。
何かアイデアはありますか?
解決方法は?
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のシェイプでも可能なはずです。これはちょっと複雑で、1つのシェイプに単純化する方法があると思うのですが、今のところ、これが私の持っているものです。
緑_水平_グラデーション.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>
ハーフオーバーレイ.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>
レイヤーリスト.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でシェイプグラデーションを作成しました。次に、半分透明のグレーで長方形のシェイプを作りました。これはレイヤーリストのXMLにインライン化すれば、このような余分なファイルは不要になると思うのですが、どうでしょうか。しかし、レイヤーリストのXMLファイルには、ちょっと面倒な部分があります。私は緑のグラデーションを一番下のレイヤーとして置き、次にハーフオーバーレイを2番目のレイヤーとして置き、上から50dpだけオフセットしました。もちろん、この数値は固定された50dpではなく、常にビューサイズの半分であることが望ましいでしょう。パーセンテージは使えないと思いますが。ここから、TextViewをtest.xmlレイアウトに挿入し、layer_list.xmlファイルを背景として使用しました。高さを100dp(オーバーレイのオフセットの2倍のサイズ)に設定すると、以下のようになりました。
タダ!
もう一つの編集 : つまり、3つの別々のXMLファイルはもう必要ないのです!私は、シェイプをアイテムとしてレイヤーリストに埋め込むことができることに気づきました。つまり、もう3つの別々のXMLファイルは必要ありません!このように組み合わせて、同じ結果を得ることができます。
レイヤーリスト.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に数値を入れるとうまくいきます。
嘘です、もう一回編集します
コンテナの高さに合わせてレイヤーの描画を手動で更新する方法を発見しました。 こちら . このコードは、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);
}
});
そして、私は終わりました! ふぅー! :)
関連
-
[解決済み] Android XML drawable ファイルに円形を定義する方法を教えてください。
-
AndroidStudio reports Could not resolve all artifacts for configuration ':app:classpath'.
-
cygwinのダウンロード、インストールチュートリアル、およびCDTの「makeプログラムがパスに見つからない」バグの解消
-
ジャークとして。起動アクティビティを特定できませんでした。デフォルトのアクティビティが見つかりません アクティビティ起動中のエラー
-
Androidで発生した問題、解決策とヒント
-
ArrayAdapter は、リソース ID が TextView であることが必要です。
-
[解決済み] Bitmapオブジェクトに画像を読み込む際にOutOfMemoryが発生する問題
-
[解決済み] 同じ要素にbackground-imageとCSS3グラデーションを組み合わせるにはどうすればよいですか?
-
[解決済み] グリッドレイアウトにおけるフリングジェスチャーの検出
-
[解決済み】アンドロイドでグラデーションの背景を作る方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
プログラム "git.exe "を実行できない場合の正しい解決方法です。CreateProcessエラー=2
-
RuntimeException: アクティビティを開始できません ComponentInfo solution
-
android:EMSのプロパティ
-
IllegalStateException。ArrayAdapter は、リソース ID が TextView である必要があります。
-
Android開発で「Attempt to invoke virtual method 'XXX()' on null object reference」というヌルポインター例外に遭遇する。
-
アンドロイドスタジオでJunitのエラー問題を解決する
-
Android studioのインストールと問題発生、Emulator: PANIC: AVDのシステムパスが見つかりません。
-
SpinnerのOnItemSelectedListenerのonItemSelectedメソッドの4つのパラメーターの意味
-
アンドロイドシェイプ、グラデーション、角丸、ボーダーラインの設定
-
[解決済み】アンドロイドでグラデーションの背景を作る方法