在Android上的TextView上投下阴影

时间:2013-11-07 20:44:33

标签: java android

我有一个TextView,它在LEFT,RIGHT和BOTTOM上有边框,你可以看到以下内容: enter image description here

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>

有没有办法像这样将阴影放到右边框和下边框,使其看起来像是浮动的: enter image description here

1 个答案:

答案 0 :(得分: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)意味着必须在开发时知道大小并且无法调整大小。
  3. 我能想到执行所需阴影的最好方法是继承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的任何问题,请告诉我,我会更新我的答案,或者您可以将其添加为评论。