PVoLan
PVoLan

Reputation: 1040

Android: ImageView loses transparency

I have a list of blog posts from users with avatars. Cause of some design reasons I need to crop square avatar images into circle images.

This is my ListView xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listViewBlogs"
        style="@style/CustomListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:divider="@drawable/divider" >
    </ListView>
</LinearLayout>

<style name="CustomListView">
    <item name="android:fadingEdge">none</item>
    <item name="android:cacheColorHint">@android:color/transparent</item>
    <item name="android:divider">@null</item>
    <item name="android:listSelector">@android:color/transparent</item>
</style>

This is my ListViewItem xml (blog post content is removed from example, only author name and avatar remains)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    android:padding="6dip">

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/imageAvatar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/avatar_default2"
            android:focusable="false" 
            android:background="@color/transparent"
            android:layerType="hardware"
            />

        <TextView
            android:id="@+id/textAuthor"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:text="TextView"
            android:textColor="@color/text_dark_grey"
            android:textSize="20dip"
            android:textStyle="bold" />
    </LinearLayout>

</LinearLayout>

Here is fragment from my adapter. Images are downloaded via Internet and cached into local storage. Then cropped pixels are filled with transparent

class BlogsAdapter extends ArrayAdapter<BlogItem>{    
    //...       

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        if(v == null){
            LayoutInflater inf = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = inf.inflate(R.layout.blogs_list_item_1, null);
        }


        BlogItem item = getItem(position);

        if(item != null){

        TextView textAuthor = (TextView)v.findViewById(R.id.textAuthor);
        if(textAuthor != null){
            textAuthor.setText(item.author_name);
        }

        ImageView imageAvatar = (ImageView)v.findViewById(R.id.imageAvatar);
        if(imageAvatar != null){

            //Load image from cache
            BitmapFactory.Options op = new Options();
            op.inPreferredConfig = Bitmap.Config.ARGB_8888;
            Bitmap imageFromCache = BitmapFactory.decodeFile(item.imagepath, op);

            //Crop round. This is not quickest one solution to do it here, but it is here to make test case clear
            Bitmap bmp2 = imageFromCache.copy(Bitmap.Config.ARGB_8888, true);
            int mw = bmp2.getWidth();
            int mh = bmp2.getHeight();
            int wc = mw/2;
            int hc = mh/2;

            for(int i=0; i<mw;i++){
                for(int j=0; j<mh;j++){
                    if( Math.sqrt( (i-wc)*(i-wc) + (j-hc)*(j-hc) ) >=(wc-2) ){
                        bmp2.setPixel(i, j, Color.TRANSPARENT);
                    }
                }                   
            }

            //Set cropped image into view
            imageView.setBackgroundColor(0);
            imageView.setImageBitmap(bmp2);

        }
        return v;
    }
}

It works good enougth

Good screenshot

But when I scroll listview, transparency looses

Not so good one

I tried:

Any ideas?

Upvotes: 2

Views: 1895

Answers (2)

PVoLan
PVoLan

Reputation: 1040

I've found that images I get from Internet have different Bitmap.Config - some ARGB_8888, some RGB_565, some null. Copying of this images with imageFromCache.copy() caused inconsistent config setup for cropped image. Instead of using imageFromCache.copy() I created new Bitmap with Bitmap.create(imageFromCache.getWidth(), imageFromCache.getHeight(), Bitmap.Config.ARGB_8888), than copied manually all pixels from source to dest (using forloop), cropping "circle" pixels on the fly. This worked properly.

Upvotes: 1

R.daneel.olivaw
R.daneel.olivaw

Reputation: 2679

have you tried doing the following in your list view tag,

android:cacheColorHint="#00000000"

Upvotes: 1

Related Questions