Android Open Source - Aviary-Android-SDK Image View Drawable Overlay






From Project

Back to project page Aviary-Android-SDK.

License

The source code is released under:

AVIARY API TERMS OF USE Full Legal Agreement The following terms and conditions and the terms and conditions at http://www.aviary.com/terms (collectively, the ?Terms??) govern your use of any and ...

If you think the Android project Aviary-Android-SDK listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.aviary.android.feather.widget;
// w  w  w . j ava  2 s. co  m
import it.sephiroth.android.library.imagezoom.ImageViewTouch;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.BlurMaskFilter.Blur;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;

import com.aviary.android.feather.R;
import com.aviary.android.feather.library.graphics.drawable.EditableDrawable;
import com.aviary.android.feather.library.graphics.drawable.FeatherDrawable;
import com.aviary.android.feather.library.services.DragControllerService.DragSource;
import com.aviary.android.feather.library.services.drag.DragView;
import com.aviary.android.feather.library.services.drag.DropTarget;

public class ImageViewDrawableOverlay extends ImageViewTouch implements DropTarget {

  public static interface OnDrawableEventListener {
    void onFocusChange( DrawableHighlightView newFocus, DrawableHighlightView oldFocus );

    void onDown( DrawableHighlightView view );

    void onMove( DrawableHighlightView view );

    void onClick( DrawableHighlightView view );
  };

  private List<DrawableHighlightView> mOverlayViews = new ArrayList<DrawableHighlightView>();

  private DrawableHighlightView mOverlayView;

  private OnDrawableEventListener mDrawableListener;

  private boolean mForceSingleSelection = true;

  private DropTargetListener mDropTargetListener;

  private Paint mDropPaint;

  private Rect mTempRect = new Rect();

  private boolean mScaleWithContent = false;

  private int mOverlayStyleId;

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

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

  @Override
  protected void init( Context context, AttributeSet attrs, int defStyle ) {
    super.init( context, attrs, defStyle );
    mTouchSlop = ViewConfiguration.get( context ).getScaledDoubleTapSlop();
    mGestureDetector.setIsLongpressEnabled( false );

    Theme theme = context.getTheme();

    TypedArray array = theme.obtainStyledAttributes( attrs, R.styleable.AviaryImageViewDrawableOverlay, defStyle, 0 );
    mOverlayStyleId = array.getResourceId( R.styleable.AviaryImageViewDrawableOverlay_aviary_highlightStyle, -1 );

    array.recycle();
  }

  /**
   * Return the overlay default style
   * 
   * @return
   */
  public int getOverlayStyleId() {
    return mOverlayStyleId;
  }

  /**
   * How overlay content will be scaled/moved
   * when zomming/panning the base image
   * 
   * @param value
   *            true if content will scale according to the image
   */
  public void setScaleWithContent( boolean value ) {
    mScaleWithContent = value;
  }

  public boolean getScaleWithContent() {
    return mScaleWithContent;
  }

  /**
   * If true, when the user tap outside the drawable overlay and
   * there is only one active overlay selection is not changed.
   * 
   * @param value
   *            the new force single selection
   */
  public void setForceSingleSelection( boolean value ) {
    mForceSingleSelection = value;
  }

  public void setDropTargetListener( DropTargetListener listener ) {
    mDropTargetListener = listener;
  }

  public void setOnDrawableEventListener( OnDrawableEventListener listener ) {
    mDrawableListener = listener;
  }

  @Override
  public void setImageDrawable( android.graphics.drawable.Drawable drawable, Matrix initial_matrix, float min_zoom, float max_zoom ) {
    super.setImageDrawable( drawable, initial_matrix, min_zoom, max_zoom );
  }

  @Override
  protected void onLayoutChanged( int left, int top, int right, int bottom ) {
    super.onLayoutChanged( left, top, right, bottom );

    if ( getDrawable() != null ) {

      Iterator<DrawableHighlightView> iterator = mOverlayViews.iterator();
      while ( iterator.hasNext() ) {
        DrawableHighlightView view = iterator.next();
        view.getMatrix().set( getImageMatrix() );
        view.invalidate();
      }
    }
  }

  @Override
  protected void postTranslate( float deltaX, float deltaY ) {
    super.postTranslate( deltaX, deltaY );

    Iterator<DrawableHighlightView> iterator = mOverlayViews.iterator();
    while ( iterator.hasNext() ) {
      DrawableHighlightView view = iterator.next();
      if ( getScale() != 1 ) {
        float[] mvalues = new float[9];
        getImageMatrix().getValues( mvalues );
        final float scale = mvalues[Matrix.MSCALE_X];

        if ( !mScaleWithContent ) view.getCropRectF().offset( -deltaX / scale, -deltaY / scale );
      }

      view.getMatrix().set( getImageMatrix() );
      view.invalidate();
    }
  }

  @Override
  protected void postScale( float scale, float centerX, float centerY ) {

    if ( mOverlayViews.size() > 0 ) {
      Iterator<DrawableHighlightView> iterator = mOverlayViews.iterator();

      Matrix oldMatrix = new Matrix( getImageViewMatrix() );
      super.postScale( scale, centerX, centerY );

      while ( iterator.hasNext() ) {
        DrawableHighlightView view = iterator.next();

        if ( !mScaleWithContent ) {
          RectF cropRect = view.getCropRectF();
          RectF rect1 = view.getDisplayRect( oldMatrix, view.getCropRectF() );
          RectF rect2 = view.getDisplayRect( getImageViewMatrix(), view.getCropRectF() );

          float[] mvalues = new float[9];
          getImageViewMatrix().getValues( mvalues );
          final float currentScale = mvalues[Matrix.MSCALE_X];

          cropRect.offset( ( rect1.left - rect2.left ) / currentScale, ( rect1.top - rect2.top ) / currentScale );
          cropRect.right += -( rect2.width() - rect1.width() ) / currentScale;
          cropRect.bottom += -( rect2.height() - rect1.height() ) / currentScale;

          view.getMatrix().set( getImageMatrix() );
          view.getCropRectF().set( cropRect );
        } else {
          view.getMatrix().set( getImageMatrix() );
        }
        view.invalidate();
      }
    } else {
      super.postScale( scale, centerX, centerY );
    }
  }

  private void ensureVisible( DrawableHighlightView hv, float deltaX, float deltaY ) {
    RectF r = hv.getDrawRect();
    int panDeltaX1 = 0, panDeltaX2 = 0;
    int panDeltaY1 = 0, panDeltaY2 = 0;

    if ( deltaX > 0 ) panDeltaX1 = (int) Math.max( 0, getLeft() - r.left );
    if ( deltaX < 0 ) panDeltaX2 = (int) Math.min( 0, getRight() - r.right );

    if ( deltaY > 0 ) panDeltaY1 = (int) Math.max( 0, getTop() - r.top );

    if ( deltaY < 0 ) panDeltaY2 = (int) Math.min( 0, getBottom() - r.bottom );

    int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2;
    int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2;

    if ( panDeltaX != 0 || panDeltaY != 0 ) {
      panBy( panDeltaX, panDeltaY );
    }
  }

  @Override
  public boolean onSingleTapConfirmed( MotionEvent e ) {

    // iterate the items and post a single tap event to the selected item
    Iterator<DrawableHighlightView> iterator = mOverlayViews.iterator();
    while ( iterator.hasNext() ) {
      DrawableHighlightView view = iterator.next();
      if ( view.isSelected() ) {
        view.onSingleTapConfirmed( e.getX(), e.getY() );
        postInvalidate();
      }
    }

    return super.onSingleTapConfirmed( e );
  }

  @Override
  public boolean onDown( MotionEvent e ) {
    Log.i( LOG_TAG, "onDown" );

    mScrollStarted = false;
    mLastMotionScrollX = e.getX();
    mLastMotionScrollY = e.getY();

    // return the item being clicked
    DrawableHighlightView newSelection = checkSelection( e );
    DrawableHighlightView realNewSelection = newSelection;

    if ( newSelection == null && mOverlayViews.size() == 1 && mForceSingleSelection ) {
      // force a selection if none is selected, when force single selection is
      // turned on
      newSelection = mOverlayViews.get( 0 );
    }

    setSelectedHighlightView( newSelection );

    if ( realNewSelection != null && mScaleWithContent ) {
      RectF displayRect = realNewSelection.getDisplayRect( realNewSelection.getMatrix(), realNewSelection.getCropRectF() );
      boolean invalidSize = realNewSelection.getContent().validateSize( displayRect );

      Log.d( LOG_TAG, "invalidSize: " + invalidSize );

      if ( !invalidSize ) {
        Log.w( LOG_TAG, "drawable too small!!!" );

        float minW = realNewSelection.getContent().getMinWidth();
        float minH = realNewSelection.getContent().getMinHeight();

        Log.d( LOG_TAG, "minW: " + minW );
        Log.d( LOG_TAG, "minH: " + minH );

        float minSize = Math.min( minW, minH ) * 1.1f;

        Log.d( LOG_TAG, "minSize: " + minSize );

        float minRectSize = Math.min( displayRect.width(), displayRect.height() );

        Log.d( LOG_TAG, "minRectSize: " + minRectSize );

        float diff = minSize / minRectSize;

        Log.d( LOG_TAG, "diff: " + diff );

        Log.d( LOG_TAG, "min.size: " + minW + "x" + minH );
        Log.d( LOG_TAG, "cur.size: " + displayRect.width() + "x" + displayRect.height() );
        Log.d( LOG_TAG, "zooming to: " + ( getScale() * diff ) );

        zoomTo( getScale() * diff, displayRect.centerX(), displayRect.centerY(), DEFAULT_ANIMATION_DURATION * 1.5f );
        return true;
      }
    }

    if ( mOverlayView != null ) {
      int edge = mOverlayView.getHit( e.getX(), e.getY() );
      if ( edge != DrawableHighlightView.NONE ) {
        mOverlayView.setMode( ( edge == DrawableHighlightView.MOVE ) ? DrawableHighlightView.MOVE
            : ( edge == DrawableHighlightView.ROTATE ? DrawableHighlightView.ROTATE : DrawableHighlightView.GROW ) );
        postInvalidate();
        if ( mDrawableListener != null ) {
          mDrawableListener.onDown( mOverlayView );
        }
      }
    }

    return super.onDown( e );
  }

  @Override
  public boolean onUp( MotionEvent e ) {
    Log.i( LOG_TAG, "onUp" );

    if ( mOverlayView != null ) {
      mOverlayView.setMode( DrawableHighlightView.NONE );
      postInvalidate();
    }
    return super.onUp( e );
  }

  @Override
  public boolean onSingleTapUp( MotionEvent e ) {
    Log.i( LOG_TAG, "onSingleTapUp" );

    if ( mOverlayView != null ) {

      int edge = mOverlayView.getHit( e.getX(), e.getY() );
      if ( ( edge & DrawableHighlightView.MOVE ) == DrawableHighlightView.MOVE ) {
        if ( mDrawableListener != null ) {
          mDrawableListener.onClick( mOverlayView );
        }
        return true;
      }

      mOverlayView.setMode( DrawableHighlightView.NONE );
      postInvalidate();

      Log.d( LOG_TAG, "selected items: " + mOverlayViews.size() );

      if ( mOverlayViews.size() != 1 ) {
        setSelectedHighlightView( null );
      }
    }

    return super.onSingleTapUp( e );
  }

  boolean mScrollStarted;
  float mLastMotionScrollX, mLastMotionScrollY;

  @Override
  public boolean onScroll( MotionEvent e1, MotionEvent e2, float distanceX, float distanceY ) {
    Log.i( LOG_TAG, "onScroll" );

    float dx, dy;

    float x = e2.getX();
    float y = e2.getY();

    if ( !mScrollStarted ) {
      dx = 0;
      dy = 0;
      mScrollStarted = true;
    } else {
      dx = mLastMotionScrollX - x;
      dy = mLastMotionScrollY - y;
    }

    mLastMotionScrollX = x;
    mLastMotionScrollY = y;

    if ( mOverlayView != null && mOverlayView.getMode() != DrawableHighlightView.NONE ) {
      mOverlayView.onMouseMove( mOverlayView.getMode(), e2, -dx, -dy );
      postInvalidate();

      if ( mDrawableListener != null ) {
        mDrawableListener.onMove( mOverlayView );
      }

      if ( mOverlayView.getMode() == DrawableHighlightView.MOVE ) {
        if ( !mScaleWithContent ) {
          ensureVisible( mOverlayView, distanceX, distanceY );
        }
      }
      return true;
    } else {
      return super.onScroll( e1, e2, distanceX, distanceY );
    }
  }

  @Override
  public boolean onFling( MotionEvent e1, MotionEvent e2, float velocityX, float velocityY ) {
    Log.i( LOG_TAG, "onFling" );

    if ( mOverlayView != null && mOverlayView.getMode() != DrawableHighlightView.NONE ) return false;
    return super.onFling( e1, e2, velocityX, velocityY );
  }

  @Override
  public void onDraw( Canvas canvas ) {
    super.onDraw( canvas );

    boolean shouldInvalidateAfter = false;

    for ( int i = 0; i < mOverlayViews.size(); i++ ) {
      canvas.save( Canvas.MATRIX_SAVE_FLAG );

      DrawableHighlightView current = mOverlayViews.get( i );
      current.draw( canvas );

      // check if we should invalidate again the canvas
      if ( !shouldInvalidateAfter ) {
        FeatherDrawable content = current.getContent();
        if ( content instanceof EditableDrawable ) {
          if ( ( (EditableDrawable) content ).isEditing() ) {
            shouldInvalidateAfter = true;
          }
        }
      }

      canvas.restore();
    }

    if ( null != mDropPaint ) {
      getDrawingRect( mTempRect );
      canvas.drawRect( mTempRect, mDropPaint );
    }

    if ( shouldInvalidateAfter ) {
      postInvalidateDelayed( EditableDrawable.CURSOR_BLINK_TIME );
    }
  }

  public void clearOverlays() {
    Log.i( LOG_TAG, "clearOverlays" );
    setSelectedHighlightView( null );
    while ( mOverlayViews.size() > 0 ) {
      DrawableHighlightView hv = mOverlayViews.remove( 0 );
      hv.dispose();
    }
    mOverlayView = null;
  }

  public boolean addHighlightView( DrawableHighlightView hv ) {
    for ( int i = 0; i < mOverlayViews.size(); i++ ) {
      if ( mOverlayViews.get( i ).equals( hv ) ) return false;
    }
    mOverlayViews.add( hv );
    postInvalidate();

    if ( mOverlayViews.size() == 1 ) {
      setSelectedHighlightView( hv );
    }

    return true;
  }

  public int getHighlightCount() {
    return mOverlayViews.size();
  }

  public DrawableHighlightView getHighlightViewAt( int index ) {
    return mOverlayViews.get( index );
  }

  public boolean removeHightlightView( DrawableHighlightView view ) {
    Log.i( LOG_TAG, "removeHightlightView" );
    for ( int i = 0; i < mOverlayViews.size(); i++ ) {
      if ( mOverlayViews.get( i ).equals( view ) ) {
        DrawableHighlightView hv = mOverlayViews.remove( i );
        if ( hv.equals( mOverlayView ) ) {
          setSelectedHighlightView( null );
        }
        hv.dispose();
        return true;
      }
    }
    return false;
  }

  @Override
  protected void onZoomAnimationCompleted( float scale ) {
    Log.i( LOG_TAG, "onZoomAnimationCompleted: " + scale );
    super.onZoomAnimationCompleted( scale );

    if ( mOverlayView != null ) {
      mOverlayView.setMode( DrawableHighlightView.MOVE );
      postInvalidate();
    }
  }

  public DrawableHighlightView getSelectedHighlightView() {
    return mOverlayView;
  }

  public void commit( Canvas canvas ) {

    DrawableHighlightView hv;
    for ( int i = 0; i < getHighlightCount(); i++ ) {
      hv = getHighlightViewAt( i );
      FeatherDrawable content = hv.getContent();
      if ( content instanceof EditableDrawable ) {
        ( (EditableDrawable) content ).endEdit();
      }

      Matrix rotateMatrix = hv.getCropRotationMatrix();
      Rect rect = hv.getCropRect();

      int saveCount = canvas.save( Canvas.MATRIX_SAVE_FLAG );
      canvas.concat( rotateMatrix );
      content.setBounds( rect );
      content.draw( canvas );
      canvas.restoreToCount( saveCount );
    }
  }

  private DrawableHighlightView checkSelection( MotionEvent e ) {
    Iterator<DrawableHighlightView> iterator = mOverlayViews.iterator();
    DrawableHighlightView selection = null;
    while ( iterator.hasNext() ) {
      DrawableHighlightView view = iterator.next();
      int edge = view.getHit( e.getX(), e.getY() );
      if ( edge != DrawableHighlightView.NONE ) {
        selection = view;
      }
    }
    return selection;
  }

  public void setSelectedHighlightView( DrawableHighlightView newView ) {

    final DrawableHighlightView oldView = mOverlayView;

    if ( mOverlayView != null && !mOverlayView.equals( newView ) ) {
      mOverlayView.setSelected( false );
    }

    if ( newView != null ) {
      newView.setSelected( true );
    }

    postInvalidate();

    mOverlayView = newView;

    if ( mDrawableListener != null ) {
      mDrawableListener.onFocusChange( newView, oldView );
    }
  }

  @Override
  public void onDrop( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo ) {
    if ( mDropTargetListener != null ) {
      mDropTargetListener.onDrop( source, x, y, xOffset, yOffset, dragView, dragInfo );
    }
  }

  @Override
  public void onDragEnter( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo ) {
    mDropPaint = new Paint();
    mDropPaint.setColor( 0xff33b5e5 );
    mDropPaint.setStrokeWidth( 2 );
    mDropPaint.setMaskFilter( new BlurMaskFilter( 4.0f, Blur.NORMAL ) );
    mDropPaint.setStyle( Paint.Style.STROKE );
    invalidate();
  }

  @Override
  public void onDragOver( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo ) {}

  @Override
  public void onDragExit( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo ) {
    mDropPaint = null;
    invalidate();
  }

  @Override
  public boolean acceptDrop( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo ) {
    if ( mDropTargetListener != null ) {
      return mDropTargetListener.acceptDrop( source, x, y, xOffset, yOffset, dragView, dragInfo );
    }
    return false;
  }

  @Override
  public Rect estimateDropLocation( DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle ) {
    return null;
  }
}




Java Source Code List

com.aviary.android.feather.AlertActivity.java
com.aviary.android.feather.AviaryMainController.java
com.aviary.android.feather.FeatherActivity.java
com.aviary.android.feather.async_tasks.AsyncImageManager.java
com.aviary.android.feather.async_tasks.DownloadImageAsyncTask.java
com.aviary.android.feather.async_tasks.ExifTask.java
com.aviary.android.feather.effects.AbstractContentPanel.java
com.aviary.android.feather.effects.AbstractOptionPanel.java
com.aviary.android.feather.effects.AbstractPanelLoaderService.java
com.aviary.android.feather.effects.AbstractPanel.java
com.aviary.android.feather.effects.AdjustEffectPanel.java
com.aviary.android.feather.effects.BordersPanel.java
com.aviary.android.feather.effects.ColorSplashPanel.java
com.aviary.android.feather.effects.CropPanel.java
com.aviary.android.feather.effects.DelayedSpotDrawPanel.java
com.aviary.android.feather.effects.DrawingPanel.java
com.aviary.android.feather.effects.EffectsPanel.java
com.aviary.android.feather.effects.EnhanceEffectPanel.java
com.aviary.android.feather.effects.MemePanel.java
com.aviary.android.feather.effects.NativeEffectRangePanel.java
com.aviary.android.feather.effects.SimpleStatusMachine.java
com.aviary.android.feather.effects.SliderEffectPanel.java
com.aviary.android.feather.effects.StickersPanel.java
com.aviary.android.feather.effects.TextPanel.java
com.aviary.android.feather.effects.TiltShiftPanel.java
com.aviary.android.feather.graphics.CdsPreviewTransformer.java
com.aviary.android.feather.graphics.GalleryBottomIndicatorDrawable.java
com.aviary.android.feather.graphics.GalleryTopIndicatorDrawable.java
com.aviary.android.feather.graphics.GlowBitmapDrawable.java
com.aviary.android.feather.graphics.GlowDrawable.java
com.aviary.android.feather.graphics.PluginDividerDrawable.java
com.aviary.android.feather.graphics.PreviewFillColorDrawable.java
com.aviary.android.feather.graphics.PreviewSpotDrawable.java
com.aviary.android.feather.graphics.RepeatableHorizontalDrawable.java
com.aviary.android.feather.opengl.AviaryGLSurfaceView.java
com.aviary.android.feather.utils.PackIconCallable.java
com.aviary.android.feather.utils.SimpleBitmapCache.java
com.aviary.android.feather.utils.ThreadUtils.java
com.aviary.android.feather.utils.TypefaceUtils.java
com.aviary.android.feather.utils.UIUtils.java
com.aviary.android.feather.widget.AdjustImageView.java
com.aviary.android.feather.widget.AviaryAbsSpinner.java
com.aviary.android.feather.widget.AviaryAdapterView.java
com.aviary.android.feather.widget.AviaryBadgeToolLayout.java
com.aviary.android.feather.widget.AviaryBottomBarViewFlipper.java
com.aviary.android.feather.widget.AviaryButton.java
com.aviary.android.feather.widget.AviaryEdgeEffect.java
com.aviary.android.feather.widget.AviaryGalleryTopIndicatorView.java
com.aviary.android.feather.widget.AviaryGallery.java
com.aviary.android.feather.widget.AviaryHighlightImageButton.java
com.aviary.android.feather.widget.AviaryImageRestoreSwitcher.java
com.aviary.android.feather.widget.AviaryImageSwitcher.java
com.aviary.android.feather.widget.AviaryNavBarViewFlipper.java
com.aviary.android.feather.widget.AviarySeekBar.java
com.aviary.android.feather.widget.AviaryTextView.java
com.aviary.android.feather.widget.AviaryToast.java
com.aviary.android.feather.widget.AviaryToggleButton.java
com.aviary.android.feather.widget.AviaryWheel.java
com.aviary.android.feather.widget.AviaryWorkspaceIndicator.java
com.aviary.android.feather.widget.AviaryWorkspace.java
com.aviary.android.feather.widget.CellLayout.java
com.aviary.android.feather.widget.CropImageView.java
com.aviary.android.feather.widget.DrawableHighlightView.java
com.aviary.android.feather.widget.EffectThumbLayout.java
com.aviary.android.feather.widget.HighlightView.java
com.aviary.android.feather.widget.IAPBuyButton.java
com.aviary.android.feather.widget.IAPDialogDetail.java
com.aviary.android.feather.widget.IAPDialogList.java
com.aviary.android.feather.widget.IAPDialogMain.java
com.aviary.android.feather.widget.ImageViewDrawableOverlay.java
com.aviary.android.feather.widget.ImageViewSpotDraw.java
com.aviary.android.feather.widget.ImageViewTiltiShiftTouch.java
com.aviary.android.feather.widget.ImageViewTouchAndDraw.java
com.aviary.android.feather.widget.PointCloud.java
com.aviary.android.feather.widget.ScrollerRunnable.java
com.aviary.android.feather.widget.VibrationHelper.java
com.aviary.android.feather.widget.VibrationWidget.java