Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

Java Imageview problem

Right ive got this code that makes the image turn into a circle and it does it using a listview but as seen in the photo it dies when it goes to the end of the photo (the last few pixels are carried on when there not supposed to. I dont want the photo to take up the whole page just the size of the photo. Ill put the code in here and the xml but yeah please help....

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

Stream item xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</RelativeLayout>

activity stream xml:

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_list"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:divider="@null"
    android:dividerHeight="0px"
    android:drawSelectorOnTop="true"
    tools:context=".StreamActivity" />

main code:

package com.example.roundrectshader;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ComposeShader;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class StreamActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_stream);

        StreamAdapter adapter = new StreamAdapter(this);
        ((ListView) findViewById(R.id.main_list)).setAdapter(adapter);

        adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
        adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
        adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));
        adapter.add(new StreamItem(this, R.drawable.testimage1, null, null));

    }

    class StreamItem {
        final Bitmap mBitmap;


        StreamItem(Context c, int resid, String line1, String line2) {
            mBitmap = BitmapFactory.decodeResource(c.getResources(), resid);

        }
    }

    class StreamDrawable extends Drawable {
        private static final boolean USE_VIGNETTE = true;

        private final float mCornerRadius;
        private final RectF mRect = new RectF();
        private final BitmapShader mBitmapShader;
        private final Paint mPaint;
        private final int mMargin;

        StreamDrawable(Bitmap bitmap, float cornerRadius, int margin) {
            mCornerRadius = cornerRadius;

            mBitmapShader = new BitmapShader(bitmap,
                    Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setShader(mBitmapShader);

            mMargin = margin;
        }

        @Override
        protected void onBoundsChange(Rect bounds) {
            super.onBoundsChange(bounds);
            mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);

            if (USE_VIGNETTE) {
                RadialGradient vignette = new RadialGradient(
                        mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
                        new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
                        Shader.TileMode.CLAMP);

                Matrix oval = new Matrix();
                oval.setScale(1.0f, 0.7f);
                vignette.setLocalMatrix(oval);

                mPaint.setShader(
                        new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
            }
        }

        @Override
        public void draw(Canvas canvas) {
            canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }

        @Override
        public void setAlpha(int alpha) {
            mPaint.setAlpha(alpha);
        }

        @Override
        public void setColorFilter(ColorFilter cf) {
            mPaint.setColorFilter(cf);
        }       
    }


    class StreamAdapter extends ArrayAdapter<StreamItem> {
        private static final int CORNER_RADIUS =100; // dips
        private static final int MARGIN = 1; // dips

        private final int mCornerRadius;
        private final int mMargin;
        private final LayoutInflater mInflater;

        public StreamAdapter(Context context) {
            super(context, 0);

            final float density = context.getResources().getDisplayMetrics().density;
            mCornerRadius = (int) (CORNER_RADIUS * density + 0.5f);
            mMargin = (int) (MARGIN * density + 0.5f);

            mInflater = LayoutInflater.from(getContext());
        }

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

            if (convertView == null) {
                view = (ViewGroup) mInflater.inflate(R.layout.stream_item, parent, false);
            } else {
                view = (ViewGroup) convertView;
            }

            StreamItem item = getItem(position);

            StreamDrawable d = new StreamDrawable(item.mBitmap, mCornerRadius, mMargin);
            view.setBackgroundDrawable(d);

            int w = item.mBitmap.getWidth();
            int h = item.mBitmap.getHeight();

            float ratio = w / (float) h;

            LayoutParams lp = view.getLayoutParams();
            lp.width = getContext().getResources().getDisplayMetrics().widthPixels;
            lp.height = (int) (lp.width / ratio);

            return view;
        }
    }
}

4 Answers

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

Without taking this code and plugging it into a project for troubleshooting...

It looks like you are setting your StreamDrawable as the background for the RelativeLayout container of stream_item.xml. The RelativeLayout is matching the width of the parent (i.e. the whole screen):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</RelativeLayout>

I think you want to add an ImageView to the RelativeLayout and set the ImageView to "wrap_content" all around. Something like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <ImageView 
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true" />

</RelativeLayout>

Then, instead of view.setBackgroundDrawable(d); in getView(), do something like:

ImageView imageView = (ImageView) view.findViewById(R.id.imageView1);
imageView.setBackgroundDrawable(d);

I don't think your last few lines setting lp are doing anything because you never use lp in a call to setLayoutParams(), like this:

imageView.setLayoutParams(lp);

I don't think you need those last few lines if you get the XML layout correct, but you might have to play around a bit.

Hope this helps...

((ImageView) findViewById(R.id.imageView1)).setAdapter(adapter);

now that lines comes up with the error: The method setAdapter(StreamActivity.StreamAdapter) is undefined for the type ImageView

Ben Jakuben
STAFF
Ben Jakuben
Treehouse Teacher

So the setAdapter() method is a method of the ListActivity class, and is normally called from the onCreate() method like this:

setAdapter(adapter);

Your class is extending a regular Activity, which is why you need the extra code in front of setAdapter() to get a ListView. It looks like you can change that line of code back to:

((ListView) findViewById(R.id.main_list)).setAdapter(adapter);

Again, not sure exactly how this will all work out without my own working project, but hopefully this makes sense and helps.

still coming up with errors :( plus really dont know what were changing or doing