2015-04-13 3 views
0

Я пытаюсь реализовать простую «скретч-карту». Код java взят андроидной демонстрацией о картине (WHERE to find Android "Fingerpaint" demo? (Android Studio era)), и я хочу просто показать изображение под поверхностью.создание скретч-карты android

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

<ImageView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:src="@drawable/android" 
    android:scaleType="fitXY" 
    /> 

<com.example.jammtup.ErasableView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    /></RelativeLayout> 

код Java:

public class ErasableView extends SurfaceView { 

private Bitmap mBitmap; 
private Canvas mCanvas; 
private Paint mPaint; 
private Path mPath; 
private Paint mBitmapPaint; 


public ErasableView(Context context) { 
    super(context); 
    mPaint = new Paint(); 
    mPath = new Path(); 
    mBitmapPaint = new Paint(Paint.DITHER_FLAG); 
} 


public void init() { 

    setFocusableInTouchMode(true); 


    mPaint.setAntiAlias(true); 
    mPaint.setDither(true); 
    mPaint.setColor(Color.TRANSPARENT); 
    mPaint.setStyle(Paint.Style.STROKE); 
    mPaint.setStrokeWidth(64); 
    mPaint.setColor(0xFFFF0000); 
    mPaint.setStrokeCap(Paint.Cap.ROUND); 
    mPaint.setStrokeJoin(Paint.Join.ROUND); 
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 

} 


@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
    mCanvas = new Canvas(mBitmap); 

} 


@Override 
protected void onDraw(Canvas canvas) { 

    canvas.drawColor(Color.TRANSPARENT); 
    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint); 
    canvas.drawPath(mPath, mPaint); 
} 



private float mX, mY; 
private static final float TOUCH_TOLERANCE = 4; 

private void touch_start(float x, float y) { 
    mPath.reset(); 
    mPath.moveTo(x, y); 
    mX = x; 
    mY = y; 
} 

private void touch_move(float x, float y) { 
    float dx = Math.abs(x - mX); 
    float dy = Math.abs(y - mY); 
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 
     mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); 
     mX = x; 
     mY = y; 
    } 
} 

private void touch_up() { 
    mPath.lineTo(mX, mY); 
    // commit the path to our offscreen 
    mCanvas.drawPath(mPath, mPaint); 
    // kill this so we don't double draw 
    mPath.reset(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    float x = event.getX(); 
    float y = event.getY(); 

    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      touch_start(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      touch_move(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_UP: 
      touch_up(); 
      invalidate(); 
      break; 
    } 
    return true; 
} } 

, что я получаю черный вид не стираемой. Это не позволяет показать изображение ниже.

Мне нужна ваша помощь !!

+0

вы никогда ничего не делать с холст, на который вы опираетесь. – njzk2

+0

может у объяснить немного больше ..... я новичок в android ... – max85

+0

мой плохой, я не видел 'canvas.drawBitmap (mBitmap, 0, 0, mBitmapPaint);' line. игнорировать мой предыдущий комментарий. – njzk2

ответ

0

Попробуйте использовать это вместо того, чтобы ваш взгляд Если вы хотите, чтобы весь проект просто проверить мое хранилище GitHub https://github.com/amarvadla/ScratchCoupon

import android.content.Context; 
    import android.graphics.Bitmap; 
    import android.graphics.BitmapFactory; 
    import android.graphics.Canvas; 
    import android.graphics.Paint; 
    import android.graphics.Path; 
    import android.graphics.PorterDuff; 
    import android.graphics.PorterDuffXfermode; 
    import android.graphics.Rect; 
    import android.graphics.drawable.BitmapDrawable; 
    import android.os.AsyncTask; 
    import android.support.v4.content.ContextCompat; 
    import android.text.TextPaint; 
    import android.util.AttributeSet; 
    import android.view.Gravity; 
    import android.view.MotionEvent; 
    import android.widget.TextView; 

общественного класса ScratchTextView расширяет TextView {

Bitmap scratchBitmap; 
public interface IRevealListener { 
    public void onRevealed(ScratchTextView tv); 
    public void onRevealPercentChangedListener(ScratchTextView stv, float percent); 
} 

public static final float STROKE_WIDTH = 12f; 

private float mX, mY; 
private static final float TOUCH_TOLERANCE = 4; 

/** 
* Bitmap holding the scratch region. 
*/ 
private Bitmap mScratchBitmap; 

/** 
* Drawable canvas area through which the scratchable area is drawn. 
*/ 
public static Canvas mCanvas; 

/** 
* Path holding the erasing path done by the user. 
*/ 
private Path mErasePath; 

/** 
* Path to indicate where the user have touched. 
*/ 
private Path mTouchPath; 

/** 
* Paint properties for drawing the scratch area. 
*/ 
private Paint mBitmapPaint; 

/** 
* Paint properties for erasing the scratch region. 
*/ 
private Paint mErasePaint; 

/** 
* Gradient paint properties that lies as a background for scratch region. 
*/ 
private Paint mGradientBgPaint; 

/** 
* Sample Drawable bitmap having the scratch pattern. 
*/ 
private BitmapDrawable mDrawable; 


/** 
* Listener object callback reference to send back the callback when the text has been revealed. 
*/ 
private IRevealListener mRevealListener; 

/** 
* Reveal percent value. 
*/ 
private float mRevealPercent; 

/** 
* Thread Count 
*/ 
private int mThreadCount = 0; 



public ScratchTextView(Context context) { 
    super(context); 
    init(); 

} 

public ScratchTextView(Context context, AttributeSet set) { 
    super(context, set); 
    init(); 
} 

public ScratchTextView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(); 
} 

/** 
* Set the strokes width based on the parameter multiplier. 
* @param multiplier can be 1,2,3 and so on to set the stroke width of the paint. 
*/ 
public void setStrokeWidth(int multiplier) { 
    mErasePaint.setStrokeWidth(multiplier * STROKE_WIDTH); 
} 

/** 
* Initialises the paint drawing elements. 
*/ 
private void init() { 


    mTouchPath = new Path(); 

    mErasePaint = new Paint(); 
    mErasePaint.setAntiAlias(true); 
    mErasePaint.setDither(true); 
    mErasePaint.setColor(0xFFFF0000); 
    mErasePaint.setStyle(Paint.Style.STROKE); 
    mErasePaint.setStrokeJoin(Paint.Join.BEVEL); 
    mErasePaint.setStrokeCap(Paint.Cap.ROUND); 
    mErasePaint.setXfermode(new PorterDuffXfermode(
      PorterDuff.Mode.CLEAR)); 
    setStrokeWidth(6); 

    mGradientBgPaint = new Paint(); 

    mErasePath = new Path(); 
    mBitmapPaint = new Paint(Paint.DITHER_FLAG); 


    scratchBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.spiderman); 
    mDrawable = new BitmapDrawable(getResources(), scratchBitmap); 


} 

@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
    super.onSizeChanged(w, h, oldw, oldh); 
    mScratchBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
    mCanvas = new Canvas(mScratchBitmap); 

    Rect rect = new Rect(0, 0, mScratchBitmap.getWidth(), mScratchBitmap.getHeight()); 
    mDrawable.setBounds(rect); 

    int startGradientColor = ContextCompat.getColor(getContext(), R.color.colorPrimary); 
    int endGradientColor = ContextCompat.getColor(getContext(), R.color.colorAccent); 

    mCanvas.drawRect(rect, mGradientBgPaint); 
    mDrawable.draw(mCanvas); 
} 

@Override 
protected void onDraw(Canvas canvas) { 

    super.onDraw(canvas); 
    canvas.drawBitmap(mScratchBitmap, 0, 0, mBitmapPaint); 
    canvas.drawPath(mErasePath, mErasePaint); 

} 

private void touch_start(float x, float y) { 
    mErasePath.reset(); 
    mErasePath.moveTo(x, y); 
    mX = x; 
    mY = y; 
} 


private void touch_move(float x, float y) { 

    float dx = Math.abs(x - mX); 
    float dy = Math.abs(y - mY); 
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { 
     mErasePath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2); 
     mX = x; 
     mY = y; 

     drawPath(); 
    } 

    mTouchPath.reset(); 
    mTouchPath.addCircle(mX, mY, 30, Path.Direction.CW); 

} 

private void drawPath() { 
    mErasePath.lineTo(mX, mY); 
    // commit the path to our offscreen 
    mCanvas.drawPath(mErasePath, mErasePaint); 
    // kill this so we don't double draw 
    mTouchPath.reset(); 
    mErasePath.reset(); 
    mErasePath.moveTo(mX, mY); 

    checkRevealed(); 
} 

/** 
* Reveals the hidden text by erasing the scratch area. 
*/ 
public void reveal() { 

    int[] bounds = getTextBounds(1.5f); 
    int left = bounds[0]; 
    int top = bounds[1]; 
    int right = bounds[2]; 
    int bottom = bounds[3]; 

    Paint paint = new Paint(); 
    paint.setXfermode(new PorterDuffXfermode(
      PorterDuff.Mode.CLEAR)); 

    mCanvas.drawRect(left, top, right, bottom, paint); 
    checkRevealed(); 
    invalidate(); 
} 


@Override 
public boolean onTouchEvent(MotionEvent event) { 
    float x = event.getX(); 
    float y = event.getY(); 

    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      touch_start(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      touch_move(x, y); 
      invalidate(); 
      break; 
     case MotionEvent.ACTION_UP: 
      drawPath(); 
      invalidate(); 
      break; 
     default: 
      break; 
    } 
    return true; 
} 

public int getColor() { 
    return mErasePaint.getColor(); 
} 


public void setRevealListener(IRevealListener listener) { 
    this.mRevealListener = listener; 
} 

public boolean isRevealed() { 
    return mRevealPercent == 1; 
} 

private void checkRevealed() { 

    if(! isRevealed() && mRevealListener != null) { 

     int[] bounds = getTextBounds(); 
     int left = bounds[0]; 
     int top = bounds[1]; 
     int width = bounds[2] - left; 
     int height = bounds[3] - top; 


     // Do not create multiple calls to compare. 
     if(mThreadCount > 1) { 
      return; 
     } 

     mThreadCount++; 

     new AsyncTask<Integer, Void, Float>() { 

      @Override 
      protected Float doInBackground(Integer... params) { 

       try { 
        int left = params[0]; 
        int top = params[1]; 
        int width = params[2]; 
        int height = params[3]; 

        Bitmap croppedBitmap = Bitmap.createBitmap(mScratchBitmap, left, top, width, height); 

        return BitmapUtils.getTransparentPixelPercent(croppedBitmap); 
       } finally { 
        mThreadCount--; 

       } 
      } 

      public void onPostExecute(Float percentRevealed) { 

       // check if not revealed before. 
       if(! isRevealed()) { 

        float oldValue = mRevealPercent; 
        mRevealPercent = percentRevealed; 

        if(oldValue != percentRevealed) { 
         mRevealListener.onRevealPercentChangedListener(ScratchTextView.this, percentRevealed); 
        } 

        // if now revealed. 
        if(isRevealed()) { 
         mRevealListener.onRevealed(ScratchTextView.this); 
        } 
       } 
      } 
     }.execute(left, top, width, height); 

    } 
} 


private static int[] getTextDimens(String text, Paint paint) { 

    int end = text.length(); 
    Rect bounds = new Rect(); 
    paint.getTextBounds(text, 0, end, bounds); 
    int width = bounds.left + bounds.width(); 
    int height = bounds.bottom + bounds.height(); 

    return new int[] { width, height}; 
} 

private int[] getTextBounds() { 
    return getTextBounds(1f); 
} 

private int[] getTextBounds(float scale) { 

    int paddingLeft = getPaddingLeft(); 
    int paddingTop = getPaddingTop(); 
    int paddingRight = getPaddingRight(); 
    int paddingBottom = getPaddingBottom(); 

    int vwidth = getWidth(); 
    int vheight = getHeight(); 

    int centerX = vwidth/2; 
    int centerY = vheight/2; 


    TextPaint paint = getPaint(); 

    String text = getText().toString(); 

    int[] dimens = getTextDimens(text, paint); 
    int width = dimens[0]; 
    int height = dimens[1]; 

    int lines = getLineCount(); 
    height = height * lines; 
    width = width/lines; 


    int left = 0; 
    int top = 0; 

    if(height > vheight) { 
     height = vheight - (paddingBottom + paddingTop); 
    } 
    else { 
     height = (int) (height * scale); 
    } 

    if(width > vwidth) { 
     width = vwidth - (paddingLeft + paddingRight); 
    } 
    else { 
     width = (int) (width * scale); 
    } 

    int gravity = getGravity(); 


    //todo Gravity.START 
    if((gravity & Gravity.LEFT) == Gravity.LEFT) { 
     left = paddingLeft; 
    } 
    //todo Gravity.END 
    else if((gravity & Gravity.RIGHT) == Gravity.RIGHT) { 
     left = (vwidth - paddingRight) - width; 
    } 
    else if((gravity & Gravity.CENTER_HORIZONTAL) == Gravity.CENTER_HORIZONTAL) { 
     left = centerX - width/2; 
    } 

    if((gravity & Gravity.TOP) == Gravity.TOP) { 
     top = paddingTop; 
    } 
    else if((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) { 
     top = (vheight - paddingBottom) - height; 
    } 

    else if((gravity & Gravity.CENTER_VERTICAL) == Gravity.CENTER_VERTICAL) { 
     top = centerY - height/2; 
    } 

    return new int[] {left, top, left + width, top + height}; 
} 
Смежные вопросы