2012-02-27 16 views
17

Potrzebuję zrobić widok miniatur z zaokrąglonymi narożnikami i wewnętrznym cieniem. Zwykle robię klatki ImageView z 9-punktami, które dobrze mi służyły, ale tym razem potrzebny mi efekt wymaga narysowania wewnętrznego cienia na górze obrazu (a nie tylko wokół niego). To skłoniło mnie do rozszerzenia klasy ImageView i zastąpienia metody onDraw().ImageView z zaokrąglonymi rogami i wewnętrznym cieniem

public class ThumbnailImageView extends ImageView { 

Po wielu tutoriali (! Dzięki StackOverflow), skończyło się z tym kodem na() metoda OnDraw:

@Override 
protected void onDraw(Canvas canvas) { 
    if (mBitmap == null) { 
     return; 
    } 

    int radius = 4; 
    int padding = 2; 
    int bleed = 2; 
    RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding); 

    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    mPaint.setColor(0xFF000000); 
    canvas.drawRoundRect(frame, radius, radius, mPaint); 

    Shader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP); 
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    mPaint.setColor(0xFF000000); 
    mPaint.setMaskFilter(new BlurMaskFilter(bleed, Blur.INNER)); 
    mPaint.setShader(bitmapShader); 
    canvas.drawRoundRect(frame, radius, radius, mPaint); 
} 

Co mam w zasadzie robi, jest rysunek pierwszy czarny zaokrąglony prostokąt a następnie narysowanie zaokrąglonej bitmapy z blaknącymi krawędziami (z BlurMaskFilter) na wierzchu. Rezultatem jest to, co chcę: wartość onDraw() result mBitmap jest zainicjowany w konstruktorze ImageView tak:

mDrawable = getDrawable(); 
if (mDrawable != null) { 
    mBitmap = ((BitmapDrawable) mDrawable).getBitmap(); 
} 

Problemem jest to, że jestem nadrzędnymi OnDraw() minimum (nie super.onDraw()) jest nazywany , więc muszę wstępnie przeskalować wszystkie obrazy do pożądanego rozmiaru miniatur (np. 96x96) lub tylko lewy górny róg obrazu zostanie narysowany. Co chcę być w stanie zrobić to wykorzystać wszystkie skalowania ramy robi kiedy przypisać następujące wartości xml do ThumbnailImageView:

android:id="@+id/thumb" 
android:layout_width="96dp" 
android:layout_height="wrap_content" 
android:adjustViewBounds="true" 
android:scaleType="fitCenter" 

Aby to zrobić, myślałem, że jakoś nazwać super.onDraw() podczas uzyskiwania efektów, których potrzebuję w tym samym czasie. Udało mi się uzyskać zaokrąglony prostokąt przez dodanie ścieżki przycinającej do płótna, ale nie mogę znaleźć sposobu na dodanie cienia wewnętrznego. Jest to nowy OnDraw() kod:

@Override 
protected void onDraw(Canvas canvas) { 
    int radius = 4; 
    int padding = 4;   
    RectF frame = new RectF(padding, padding, getWidth() - padding, getHeight() - padding); 
    Path clipPath = new Path(); 
    clipPath.addRoundRect(frame, radius, radius, Path.Direction.CW); 
    canvas.clipPath(clipPath); 
    super.onDraw(canvas); 
    // add inner shadow 
} 

widzę dwie możliwości:

1) Aby poprawnie pre skalę bitmapy ImageView za. Ale gdzie jest najlepsze miejsce, aby to zrobić? W jego konstruktorze? W metodzie onDraw(), w której struktura wydaje się to robić? Czy framework zmienia rozmiary dowolnej mapy bitowej, czy też jest inny sposób narysowania skalowanego obrazu na płótnie bez negatywnego wpływu na wydajność?

2) Aby dodać wewnętrzną warstwę cienia do tego, co rysuje rysunek super.onDraw(), ale brakuje mi pomysłów, jak to zrobić.

Każda pomoc zostanie doceniona.

Dzięki!

Odpowiedz

11

Spójrz na Erica (od squareup) Materiał Prezentacja z konferencji AndoridOpen oreilly w ubiegłym roku w swoim wykładzie pt Beautiful Android Ma mnóstwo informacji, które powinny pomóc.

Chciałbym, żeby gdzieś mieli film z jego prezentacji. Nie mogę tego znaleźć. Bardzo przepraszam.

EDIT: Dzięki @mykola dla yt link

+1

+1 za bardzo użyteczną linku :) – Wesley

+1

tu jest link do filmu http://www.youtube.com/watch?v=jF6Ad4GYjRU – mykola

+0

@Mojola OMG. rządzisz. dzięki za link yt !!!! – petey

Powiązane problemy