Diferentes tipos de ImageView – RoundedImageView e TouchImageView

RoundedImageView

Em algumas situações, fica elegante acrescentar uma imagem em uma moldura arredondada. Invés do tradicional ImageView quadrado disponibilizado pela API do Android.

Para esses momentos você poderá utilizar o componente abaixo:

public class RoundedImageView extends ImageView {

	public RoundedImageView(Context context) {
		super(context);
	}

	public RoundedImageView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	protected void onDraw(Canvas canvas) {

		Drawable drawable = getDrawable();

		if (drawable == null) {
			return;
		}

		if (getWidth() == 0 || getHeight() == 0) {
			return; 
		}
		Bitmap b =  ((BitmapDrawable)drawable).getBitmap() ;
		Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

		int w = getWidth();


		Bitmap roundBitmap =  getCroppedBitmap(bitmap, w);
		canvas.drawBitmap(roundBitmap, 0,0, null);

	}

	public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
		Bitmap sbmp;
		
		if(bmp.getWidth() != radius || bmp.getHeight() != radius)
			sbmp = Bitmap.createScaledBitmap(bmp, radius, radius, false);
		else
			sbmp = bmp;
		
		Bitmap output = Bitmap.createBitmap(sbmp.getWidth(),
				sbmp.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, sbmp.getWidth(), sbmp.getHeight());

		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setDither(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(Color.parseColor("#BAB399"));
		canvas.drawCircle(sbmp.getWidth() / 2+0.7f, sbmp.getHeight() / 2+0.7f,
				sbmp.getWidth() / 2+0.1f, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(sbmp, rect, rect, paint);


		return output;
	}

}

Como Utiliza-lo

No seu layout XML, onde você costumava usar o ImageView. Passe o caminho completo do seu novo componente, o RoundedImageView.

No caso do meu projeto, o código do Layout XML ficaria assim:

   <br.com.lvc.utility.screen.component.RoundedImageView
                    android:id="@+id/image_view_humor"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/corneteiro" />

Resultado final

rounded_image_view

TouchImageView

Outra classe que herda de ImageView e também pode ser muito útil é o TouchImageView que permite que o usuário mova a imagem livremente.
Segue o código deste componente abaixo, para utiliza-lo basta executar os mesmos procedimentos do RoundedImageView, bastando apenas trocar o nome.

public class TouchImageView extends ImageView implements OnTouchListener {

    private static final String TAG = "Touch";
    // These matrices will be used to move and zoom image
    Matrix matrix = new Matrix();
    Matrix savedMatrix = new Matrix();

    // We can be in one of these 3 states
    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    // Remember some things for zooming
    PointF start = new PointF();
    PointF mid = new PointF();
    float oldDist = 1f;

    Context context;

    //Acionado quando o componete for recuperado de um arquivo XML.
	public TouchImageView(Context context, AttributeSet attrs) {	
		super(context, attrs);
		configureScreen(context);
	}

    public TouchImageView(Context context) {
        super(context);
        configureScreen(context);
    }
    
    private void configureScreen(Context context) {
    	setClickable(true);
        this.context = context;

        matrix.setTranslate(1f, 1f);
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(this);
    }


    public void setImage(Bitmap bm, int displayWidth, int displayHeight) { 
        super.setImageBitmap(bm);

        //Fit to screen.
        float scale;
        if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())){
            scale =  (float)displayWidth / (float)bm.getWidth();
        } else {
            scale = (float)displayHeight / (float)bm.getHeight();
        }

        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postScale(scale, scale, mid.x, mid.y);
        setImageMatrix(matrix);


        // Center the image
        float redundantYSpace = (float)displayHeight - (scale * (float)bm.getHeight()) ;
        float redundantXSpace = (float)displayWidth - (scale * (float)bm.getWidth());

        redundantYSpace /= (float)2;
        redundantXSpace /= (float)2;


        savedMatrix.set(matrix);
        matrix.set(savedMatrix);
        matrix.postTranslate(redundantXSpace, redundantYSpace);
        setImageMatrix(matrix);
    }

    /** Determine the space between the first two fingers */
    private float spacing(WrapMotionEvent event) {
        // ...
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, WrapMotionEvent event) {
        // ...
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    @Override
    public boolean onTouch(View v, MotionEvent rawEvent) {
        WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            Log.d(TAG, "mode=DRAG");
            mode = DRAG;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            Log.d(TAG, "oldDist=" + oldDist);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
                Log.d(TAG, "mode=ZOOM");
            }
            break;
        case MotionEvent.ACTION_UP:
        	 Log.d(TAG, "mode=UP");
        	 try {
            int xDiff = (int) Math.abs(event.getX() - start.x);
            int yDiff = (int) Math.abs(event.getY() - start.y);
            if (xDiff < 8 && yDiff < 8){
                performClick();
            }
        	 } catch (Exception ex)
        	 {
        		 Log.d(TAG, "Problema UP");
        	 }
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            Log.d(TAG, "mode=NONE");
            break;
        case MotionEvent.ACTION_MOVE:
        	 try {
            if (mode == DRAG) {
            	Log.d(TAG, "mode=MOVE");
                // ...
                matrix.set(savedMatrix);
                matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
            } else if (mode == ZOOM) {
                float newDist = spacing(event);
                Log.d(TAG, "newDist=" + newDist);
                if (newDist > 10f) {
                    matrix.set(savedMatrix);
                    float scale = newDist / oldDist;
                    matrix.postScale(scale, scale, mid.x, mid.y);
                }
            }
        	 } catch (Exception ex)
        	 {
        		 Log.d(TAG, "Problema action MOVE");
        	 }
            break;
        }

        setImageMatrix(matrix);
        return true; // indicate event was handled
    }
}
Anúncios

, , ,

  1. #1 by Claudio Ramos on Maio 5, 2015 - 5:48 pm

    show de bola parabens, vou usar como biblioteca , cara vc poderia explicar o codigo ! como foi feito…? valeu

  2. #2 by Luiz Paulo Mariath on Janeiro 31, 2015 - 7:35 pm

    Boa tarde, utilizei o RoundedImageView numa listview e ela funcionou e numa outra listview onde os dados vem do banco não funcionou, tem algum método diferente pra fazer nesse segundo caso?

    • #3 by Leonardo Casasanta on Fevereiro 19, 2015 - 5:16 pm

      Ola Luiz,

      Não há distinção do funcionamento do componente com a forma como os dados chegam. Se os dados chegarem certinho o RoundedImageView deverá funcionar tanto se os dados vierem do banco ou da web.

      Análise direitinho pra ver se os dados que vêm do banco (e não estão funcionando) se eles estão corretos.

      Abraço.

  3. #4 by Luiz on Janeiro 8, 2015 - 4:18 am

    Essa classe RoundedImageView seria feita dentro de outra classe ou crio uma so pra ela?

    • #5 by Leonardo Casasanta on Janeiro 9, 2015 - 3:14 am

      Sim, nesse caso não seria uma inner class. Pois você vai ter que conseguir chama-la no seu Layout.xml.

  4. #6 by Douglas on Junho 29, 2014 - 8:31 pm

    Muuito bom o exemplo. Teria o código fonte?

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: