0

我有一个 TextView,它在 LEFT、RIGHT 和 BOTTOM 上有边框,您可以看到以下内容: 在此处输入图像描述

其 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="#D30308" /> 
        </shape>
    </item>
    <item android:bottom="5dp" android:left="5dp" android:right="5dp">  
        <shape android:shape="rectangle">
            <solid android:color="#FFE5E5" />
        </shape>
    </item>
</layer-list>

有什么方法可以像这样在右侧和底部边框上放置阴影,使其看起来像浮动: 在此处输入图像描述

4

1 回答 1

0

我在等着看是否有人会用我还不知道的东西来回答这个问题,也许他们会用我知道的东西来回答。您可以执行以下操作

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:left="5dp" android:right="5dp" android:bottom="5dp">
    <shape>
        <solid android:color="#FFE5E5" />
    </shape>
</item>

<!-- 95dp assumes the width is 100 -->
<!-- Left side gradient -->
<item android:right="95dp" android:bottom="5dp">
    <shape android:dither="true">
        <gradient android:angle="180"
                  android:endColor="#00333333"
                  android:startColor="#ff333333"
                  android:type="linear"/>
    </shape>
</item>

<!-- Right side gradient -->
<item android:left="95dp" android:bottom="5dp">
    <shape android:dither="true">
        <gradient android:angle="0"
                  android:endColor="#00333333"
                  android:startColor="#ff333333"
                  android:type="linear"/>
    </shape>
</item>

<!-- Bottom gradient -->
<!-- To prevent overlap we set 10dp on left and right -->
<item android:top="95dp" android:left="5dp" android:right="5dp">
    <shape android:dither="true">
        <gradient android:angle="270"
                  android:endColor="#00333333"
                  android:startColor="#ff333333"
                  android:type="linear"/>
    </shape>
</item>

<!-- Creates the left-corner gradient -->
<item android:top="95dp" android:right="95dp">
    <shape android:dither="true">
        <gradient android:gradientRadius="15"
                  android:centerX="1"
                  android:centerY="0"
                  android:endColor="#00333333"
                  android:startColor="#ff333333"
                  android:type="radial"/>
    </shape>
</item>

<!-- Create the right-corner gradient -->
<item android:top="95dp" android:left="95dp">
    <shape android:dither="true">
        <gradient android:gradientRadius="15"
                  android:centerX="0"
                  android:centerY="0"
                  android:endColor="#00333333"
                  android:startColor="#ff333333"
                  android:type="radial"/>
    </shape>
</item>
</layer-list>

这有两个问题使它不合理。

  1. gradientRadius 值不是倾角值,因此缩放到不同的屏幕尺寸会使角落的尺寸不正确。
  2. 用于向右移动的量 (95dp) 和底部渐变意味着在开发时必须知道大小并且不能调整大小。

我能想到的执行您想要的投影的最佳方法是将 TextView 子类化并覆盖 onDraw() 函数并手动绘制类似于我在上面的 xml 中的渐变。

例如:(更新

@Override
    protected void onDraw(Canvas canvas) {
        //Gets the pixel size from dp (5)
        DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
        final int gradientWidth = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, metrics);

        final int startColor =  0x00333333;
        final int endColor =    0xff333333;

        Rect clip = new Rect();
        getDrawingRect(clip);
        int saveNumber = canvas.save(Canvas.CLIP_SAVE_FLAG);

        //Set a smaller clip rect (drawing area) so that the original background gets drawn, and our drop shadow isn't put on top
        canvas.clipRect(new Rect(clip.left + gradientWidth, clip.top + gradientWidth, clip.right - gradientWidth, clip.bottom - gradientWidth), Region.Op.REPLACE);
        super.onDraw(canvas);

        //Return to the original clip rect
        canvas.restoreToCount(saveNumber);


        Paint paint = new Paint();
        paint.setDither(true);
        paint.setAntiAlias(true);

        //The left gradient
        LinearGradient leftGradient = new LinearGradient(0, 0, gradientWidth, 0, startColor, endColor, Shader.TileMode.CLAMP);
        paint.setShader(leftGradient);
        canvas.drawRect(0, 0, gradientWidth, getHeight() - gradientWidth, paint);

        //The right gradient
        LinearGradient rightGradient = new LinearGradient(getWidth() - gradientWidth, 0, getWidth(), 0, endColor, startColor, Shader.TileMode.CLAMP);
        paint.setShader(rightGradient);
        canvas.drawRect(getWidth() - gradientWidth, 0, getWidth(), getHeight() - gradientWidth, paint);

        //The bottom gradient
        canvas.save();
        canvas.rotate(270, getWidth()/2, getHeight()/2);
        int nX = (getWidth()/2) - (getHeight()/2);
        int nY = 0 - ((getWidth()/2) - (getHeight()/2));

        LinearGradient bottomGradient = new LinearGradient(nX, nY, nX + gradientWidth, nY, startColor, endColor, Shader.TileMode.CLAMP);
        paint.setShader(bottomGradient);
        canvas.drawRect(nX, nY + gradientWidth, nX + gradientWidth, nY + getWidth() - gradientWidth, paint);
        canvas.restore();



        //Draw the bottom-left corner
        int doubleWidth = 2*gradientWidth;
        LinearGradient leftCorner = new LinearGradient(0, 0, gradientWidth, 0, startColor, endColor, Shader.TileMode.CLAMP);
        paint.setShader(leftCorner);

        Bitmap b = Bitmap.createBitmap(doubleWidth, doubleWidth, Bitmap.Config.ARGB_8888);
        Canvas bCanvas = new Canvas(b);
        bCanvas.save();
        bCanvas.rotate(315, doubleWidth/2, doubleWidth/2);

        RectF leftCornerRect = new RectF(0, 0, doubleWidth, doubleWidth);
        bCanvas.drawArc(leftCornerRect, 135, 90, true, paint);
        bCanvas.restore();

        canvas.drawBitmap(b, 0, getHeight() - doubleWidth, null);


        //Draw the bottom-right corner
        Matrix matrix = new Matrix();
        matrix.postRotate(270);
        Bitmap b2 = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);

        canvas.drawBitmap(b2, getWidth()-doubleWidth, getHeight()-doubleWidth, null);
    }

然后可以在xml中实现(修改路径为正确):

<com.so.SO_Questions.Views.SO_TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#ff000000"
            android:padding="5dp"
            android:layout_margin="10dp"
            android:background="#7799cc"
            android:text=""/>

这仍然存在一些问题,因为我目前没有时间解决它们。主要的两个是角渐变不完全匹配,所以他们需要一些调整,并且clipRect没有像我期望的那样工作,所以背景颜色正在通过。

如果您有任何问题或需要更多帮助,请告诉我。此外,如果您解决了 onDraw 的任何问题,请告诉我,我将更新我的答案,或者您可以将其添加为评论。

于 2013-11-07T23:02:21.123 回答