2013-07-22 21 views
9

Obecnie tworzę zaokrągloną wersję obrazu w mojej aplikacji, rysując na płótnie. Chciałbym narysować słabe otoczenie wokół obrazu, ale nie mogę go poprawnie zrozumieć. Mam 2 pytania: 1. W jaki sposób mogę narysować cień zewnętrzny (mogę tylko rysować cień za pomocą siekiery lub przesunięcia y) 2. Jak mogę narysować cień, aby nie zawierał artefaktów załączony obraz. Kod:Rysowanie cienia zewnętrznego podczas rysowania obrazu

![public Bitmap getRoundedCornerBitmap(Bitmap bitmap, float cornerRadius) { 
     Bitmap output = Bitmap.createBitmap(bitmap.getWidth()+6, bitmap.getHeight() +6, Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 

     final int color = 0xff424242; 
     int shadowRadius = getDipsFromPixel(3); 
     final Rect imageRect = new Rect(shadowRadius, shadowRadius, bitmap.getWidth(), bitmap.getHeight()); 
     final RectF rectF = new RectF(imageRect); 

     // This does not achieve the desired effect 
     Paint shadowPaint = new Paint(); 
     shadowPaint.setAntiAlias(true); 
     shadowPaint.setColor(Color.BLACK); 
     shadowPaint.setShadowLayer((float)shadowRadius, 2.0f, 2.0f,Color.BLACK); 
     canvas.drawOval(rectF, shadowPaint); 

     canvas.drawARGB(0, 0, 0, 0); 
     final Paint paint = new Paint(); 
     paint.setAntiAlias(true); 
     paint.setColor(color); 

     canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint); 

     paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
     canvas.drawBitmap(bitmap, imageRect, imageRect, paint); 

     return output; 
    }][1] 

http://i.stack.imgur.com/d7DV6.png

Jest to przykład efektu usiłuję osiągnąć: enter image description here

+0

@Leonidos Dołączyłem teraz przykład. Zauważysz słaby zewnętrzny cień wokół obrazu. – RunLoop

Odpowiedz

13

Zaczynamy

http://i.imgur.com/cKi1ckX.png Yup nadal kopać Nexus S

Po pierwsze, zaprzestań maskowania bitmap, które ay, możesz to zrobić bez przydzielania kolejnego Bitmap, kasy this blog post about how to draw rounded (and actually any shape) images.

drugie użyciem że Drawable prawdopodobnie mogą dowiedzieć się, jak dodać swój cień, po prostu upewnij się, że nie zostanie obcięty, na 18+ można użyć ViewOverlay s za to również pamiętać, że there are several unsupported drawing operations for hardware accelerated layers, że zawiera setShadowLayer i BlurMaskFilter, jeśli wydajność nie jest to problem dla ciebie, możesz go wyłączyć jak zawsze:

if (SDK_INT >= HONEYCOMB) { 
    view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
} 

I używać setShadowLayer jak już stara:

somePaint.setShadowLayer(shadowSize, deltaX, deltaY, shadowColor); 

Dla przykładu, sprawdź link na końcu.

Jeśli nadal chcesz być przyspieszany sprzętowo, będziesz musiał podrobić to ryzyko przekroczenia, możesz użyć gradientu radialnego lub narysować inny owal sam go zamazać (jak wspomniano wcześniej nie można użyć BlurMaskFilter) lub użyć pre -blurred Bitmap (więcej maskowania).

Dla takiego subtelnego cienia wolałbym po prostu spasować, jeśli wymagana jest wydajność, the full sauce is in the banana stand. Aktualizacja: Starting L you can use real shadows

+0

Witam, dziękuję za udzielenie odpowiedzi i wskazówki dotyczące wydajności. Niestety, jestem nowy na Androida, więc bardzo trudno jest znaleźć zewnętrzną część cienia. Jeśli mógłbyś opublikować kod pokazujący, jak stworzyć zewnętrzny cień (zobacz obrazek, który załączam do pytania), nagrodzę cię nagrodą. – RunLoop

+0

@RunLoop Zaktualizowałem moją odpowiedź, sprawdź link na dole – eveliotc

+0

Dziękuję bardzo! – RunLoop

26

Potrzebowałem podobnego efektu, ale na AppWidget niestety nie mogłem użyć rozwiązania @ EvelioTarazona. To właśnie wymyśliłem, powinien działać z bitmapą dowolnego kształtu.

final Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); 
    final Bitmap shadow = addShadow(src, src.getHeight(), src.getWidth(), Color.BLACK, 3, 1, 3); 
    final ImageView iv = (ImageView)findViewById(R.id.image); 
    iv.setImageBitmap(shadow); 

Example with parameters size=3, dx=1, dy=3, color=BLACK

public Bitmap addShadow(final Bitmap bm, final int dstHeight, final int dstWidth, int color, int size, float dx, float dy) { 
    final Bitmap mask = Bitmap.createBitmap(dstWidth, dstHeight, Config.ALPHA_8); 

    final Matrix scaleToFit = new Matrix(); 
    final RectF src = new RectF(0, 0, bm.getWidth(), bm.getHeight()); 
    final RectF dst = new RectF(0, 0, dstWidth - dx, dstHeight - dy); 
    scaleToFit.setRectToRect(src, dst, ScaleToFit.CENTER); 

    final Matrix dropShadow = new Matrix(scaleToFit); 
    dropShadow.postTranslate(dx, dy); 

    final Canvas maskCanvas = new Canvas(mask); 
    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    maskCanvas.drawBitmap(bm, scaleToFit, paint); 
    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
    maskCanvas.drawBitmap(bm, dropShadow, paint); 

    final BlurMaskFilter filter = new BlurMaskFilter(size, Blur.NORMAL); 
    paint.reset(); 
    paint.setAntiAlias(true); 
    paint.setColor(color); 
    paint.setMaskFilter(filter); 
    paint.setFilterBitmap(true); 

    final Bitmap ret = Bitmap.createBitmap(dstWidth, dstHeight, Config.ARGB_8888); 
    final Canvas retCanvas = new Canvas(ret); 
    retCanvas.drawBitmap(mask, 0, 0, paint); 
    retCanvas.drawBitmap(bm, scaleToFit, null); 
    mask.recycle(); 
    return ret; 
} 
+1

Dzięki takiemu odpowiedzi, ale kolor cienia nie działa hrer. Proszę, zasugeruj mi. –

+1

@BalvinderSingh Z chęcią pomogę, jeśli zechcesz opublikować najważniejsze informacje lub problem ze swoim problemem. Jeśli dokładnie skopiujesz/wkleisz mój kod, to powinien on działać dobrze ... – schwiz

+1

jeśli zastosuję colorFilter na obrazie, to Shadow pojawi się w kolorze, jaki zastosowałem do obrazu, ale chcę dodać inny kolor cienia –

2

Utwórz nazwę xml to round_shape.xml w rozciągliwej folderze

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval"> 

    <stroke 
     android:width="1dp" 
     android:color="#bebebe" /> 
</shape> 

Zestaw ten round_shape jako tlo widzenia obrazu jak poniżej

<ImageView 
    android:id="@+id/img_profile" 
    android:layout_width="120dp" 
    android:layout_height="120dp" 
    android:padding="2dp" 
    android:scaleType="fitXY" 
    android:src="@drawable/camera" /> 

Powyższy kod tworzyć cienką warstwę wokół widoku obrazu po masz okrągły bitmapy, poniżej funkcja zrobić

public Bitmap roundBit(Bitmap bm) { 

     Bitmap circleBitmap = Bitmap.createBitmap(bm.getWidth(), 
       bm.getHeight(), Bitmap.Config.ARGB_8888); 

     BitmapShader shader = new BitmapShader(bm, TileMode.CLAMP, 
       TileMode.CLAMP); 
     Paint paint = new Paint(); 
     paint.setShader(shader); 
     paint.setAntiAlias(true); 
     Canvas c = new Canvas(circleBitmap); 
     c.drawCircle(bm.getWidth()/2, bm.getHeight()/2, bm.getWidth()/2, 
       paint); 

     return circleBitmap; 
} 
2

enter image description here

  ImageView imageView=findViewById(R.id.iv); 
        Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.images); 
        imageView.setImageBitmap(doHighlightImage(icon)); 


      public static Bitmap doHighlightImage(Bitmap src) { 
        Bitmap bmOut = Bitmap.createBitmap(src.getWidth() + 96, src.getHeight() + 96, Bitmap.Config.ARGB_8888); 
        Canvas canvas = new Canvas(bmOut); 
        canvas.drawColor(0, Mode.CLEAR); 
        Paint ptBlur = new Paint(); 
        ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL)); 
        int[] offsetXY = new int[2]; 
        Bitmap bmAlpha = src.extractAlpha(ptBlur, offsetXY); 
        Paint ptAlphaColor = new Paint(); 
        ptAlphaColor.setColor(Color.BLACK); 
        canvas.drawBitmap(bmAlpha, offsetXY[0], offsetXY[1], ptAlphaColor); 
        bmAlpha.recycle(); 
        canvas.drawBitmap(src, 0, 0, null); 
        return bmOut; 
       } 
Powiązane problemy