11

LinearLayoutレイアウトが描画されると、その下にドロップ シャドウが追加されるように拡張したいと考えています。メソッドをオーバーライドして遊んでみましたonDrawが、少し迷っています。これまたはライブラリの提案についての助けをいただければ幸いです。

これは、私が達成しようとしているドロップ シャドウ ビューの例です。ビューの内容をホワイト ボックス内に収める必要があるため、ここで 9 パッチを使用できるとは思えません。これは、ボーダーと PNG の終わりの間の距離を知る必要があることを意味します。ただし、画面密度が異なると、この距離は常に同じ PX になりますが、同じ DP ではないことを意味すると思います。

明確にするために、レイアウトに追加されたときにドロップ シャドウがその下に描画されるように、View クラスを拡張する方法が必要です。XML または 9Patch ソリューションは使用しないでください。

ここに画像の説明を入力

ありがとう

ジャック

4

3 に答える 3

16

私はあなたの質問に対するコメントに同意します:プログラムによるドロップシャドウ効果は悪い選択であり、ここで述べたような単純な9パッチ(またはそれらのセット)で同じ効果を達成することができます。

ところで、私はあまりにも興味があり、仕事の後に解決策をハッキングすることで終わりました。

提示されたコードはテストであり、単純な概念実証として意図されている必要があります(したがって、反対票を投じないでください)。示されている操作の一部は非常に高価であり、パフォーマンスに深刻な影響を与える可能性があります(周りには多くの例があります。ここを参照してください。アイデアを得るにはここを参照してください)。これは、たまに表示されるコンポーネントの最後の手段となるはずです。

public class BalloonView extends TextView {

  protected NinePatchDrawable bg;
  protected Paint paint;
  protected Rect padding = new Rect();
  protected Bitmap bmp;

  public BalloonView(Context context) {
    super(context);
init();
  }

  public BalloonView(Context context, AttributeSet attrs) {
    super(context, attrs);
init();
  }

  public BalloonView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init();
  }

  @SuppressLint("NewApi")
  protected void init() {
    // decode the 9patch drawable
    bg = (NinePatchDrawable) getResources().getDrawable(R.drawable.balloon);

    // get paddings from the 9patch and apply them to the View
    bg.getPadding(padding);
    setPadding(padding.left, padding.top, padding.right, padding.bottom);

    // prepare the Paint to use below
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.rgb(255,255,255));
    paint.setStyle(Style.FILL);

    // this check is needed in order to get this code
    // working if target SDK>=11
    if( Build.VERSION.SDK_INT >= 11 )
      setLayerType(View.LAYER_TYPE_SOFTWARE, paint);

    // set the shadowLayer
    paint.setShadowLayer(
      padding.left * .2f, // radius
      0f, // blurX
      padding.left * .1f, // blurY
      Color.argb(128, 0, 0, 0) // shadow color
    );
  }

  @Override
  protected void onDraw(Canvas canvas) {
    int w = getMeasuredWidth();
    int h = getMeasuredHeight();

    // set 9patch bounds according to view measurement
    // NOTE: if not set, the drawable will not be drawn
    bg.setBounds(0, 0, w, h);

    // this code looks expensive: let's do once
    if( bmp == null ) {

      // it seems like shadowLayer doesn't take into account
      // alpha channel in ARGB_8888 sources...
      bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);

      // draw the given 9patch on the brand new bitmap
      Canvas tmp = new Canvas(bmp);
      bg.draw(tmp);

      // extract only the alpha channel
      bmp = bmp.extractAlpha();
    }

    // this "alpha mask" has the same shape of the starting 9patch,
    // but filled in white and **with the dropshadow**!!!!
    canvas.drawBitmap(bmp, 0, 0, paint);

    // let's paint the 9patch over...
    bg.draw(canvas);

    super.onDraw(canvas);
  }
}

まず、プログラムによるドロップシャドウを取得するには、ここPaint.setShadowLayer(...)で説明するように対処する必要があります。基本的に、カスタムビューの描画に使用されるオブジェクトのシャドウレイヤーを定義する必要があります。残念ながら、オブジェクトを使用してNinePatchDrawableを描画することはできないため、オブジェクトをビットマップに変換する必要があります(最初のハック)。さらに、シャドウレイヤーはARGB_8888画像では正しく機能しないようです。したがって、適切なシャドウを取得するために私が見つけた唯一の方法は、指定されたNinePatchDrawable(2番目のハック)のアルファマスクをそのすぐ下に描画することでした。PaintCanvasPaint

これがいくつかのショットです(Android 2.3.3@mdpiおよび4.2.2@xhdpiでテスト済み) ここに画像の説明を入力してください ここに画像の説明を入力してください

編集:念のため、テストで使用した9パッチを添付しました(に配置res/drawable/mdpiここに画像の説明を入力してください

于 2013-02-20T22:32:44.840 に答える
4

これは、レイアウト、ボタンなどに影を落とす最も簡単な方法です。 background.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item >
            <shape 
                android:shape="rectangle">
            <solid android:color="@android:color/darker_gray" />
            <corners android:radius="5dp"/>
            </shape>
        </item>
        <item android:right="1dp" android:left="1dp" android:bottom="2dp">
            <shape 
                android:shape="rectangle">
            <solid android:color="@android:color/white"/>
            <corners android:radius="5dp"/>
            </shape>
        </item>
    </layer-list>

あなたのmain.xmlで

<LineaLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/background"
/>
于 2013-02-26T07:33:23.337 に答える
3

このテクニックを試してください。

container_dropshadow.xml

`

 <!-- Drop Shadow Stack -->
 <item>
    <shape>
        <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
        <solid android:color="#00CCCCCC" />
    </shape>
</item>
 <item>
    <shape>
        <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
        <solid android:color="#10CCCCCC" />
    </shape>
</item>
 <item>
    <shape>
        <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
        <solid android:color="#20CCCCCC" />
    </shape>
</item>
 <item>
    <shape>
        <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
        <solid android:color="#30CCCCCC" />
    </shape>
</item>
<item>
    <shape>
        <padding android:top="1dp" android:right="1dp" android:bottom="1dp" android:left="1dp" />
        <solid android:color="#50CCCCCC" />
    </shape>
</item>

<!-- Background -->
<item>
<shape>
        <solid android:color="@color/white" />
    <corners android:radius="3dp" />
</shape>
</item>

次に、次のような背景として XML レイアウトに適用できます。

LinearLayout android:background="@drawable/container_dropshadow"

`

于 2013-02-18T07:19:14.547 に答える