在android中如何从自定义表面视图

时间:2015-12-28 08:52:38

标签: android

我正在创建Android应用程序,我需要从我的框架布局中获取包含imageview的位图,其次是自定义表面视图xml文件如下所示但是当我尝试从框架布局缩短屏幕时我只得到位图下面的图像不是上面的图像可以任何一个高我如何获得所有fram布局的位图

<LinearLayout
    android:id="@+id/linear"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center|center_horizontal"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:layout_marginTop="10dp"
    android:orientation="horizontal" >

    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <FrameLayout
            android:id="@+id/frmQueue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/imglow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:contentDescription="@string/app_name"
                android:scaleType="centerCrop" />

            <com.winsontan520.WScratchView
            android:id="@+id/scratch_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>

        </FrameLayout>
    </FrameLayout>
</LinearLayout>

WScratchView.java

public class WScratchView extends SurfaceView implements IWScratchView, SurfaceHolder.Callback {
private static final String TAG = "WScratchView";

// default value constants
private final int DEFAULT_COLOR = 0xff444444; // default color is dark gray
public static  int DEFAULT_REVEAL_SIZE = 30;

public static final int DEFAULT_SCRATCH_TEST_SPEED = 4;
private Context mContext;
public Bitmap mbits;
private WScratchViewThread mThread;
List<Path> mPathList = new ArrayList<Path>();
public int mOverlayColor;
public Paint mOverlayPaint;
public int mRevealSize;
private boolean mIsScratchable = true;
private boolean mIsAntiAlias = false;
private Path path;
private float startX = 0;
private float startY = 0;
private boolean mScratchStart = false;
public Bitmap mScratchBitmap;
public Drawable mScratchDrawable = null;
private Paint mBitmapPaint;
private Matrix mMatrix;
private Bitmap mScratchedTestBitmap;
public Canvas mScratchedTestCanvas;
private OnScratchCallback mOnScratchCallback;

//Enable scratch all area if mClearCanvas is true
private boolean mClearCanvas = false;
//Enable click on WScratchView if mIsClickable is true
private boolean mIsClickable = false;

public WScratchView(Context ctx, AttributeSet attrs) {
    super(ctx, attrs);
    init(ctx, attrs);
}

public WScratchView(Context context) {
    super(context);
    init(context, null);
}

private void init(Context context, AttributeSet attrs) {
    mContext = context;

    // default value
    mOverlayColor = DEFAULT_COLOR;
    mRevealSize = DEFAULT_REVEAL_SIZE;

    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WScratchView, 0, 0);

    final int indexCount = ta.getIndexCount();
    for (int i = 0; i < indexCount; i++) {
        int attr = ta.getIndex(i);
        if (attr == R.styleable.WScratchView_overlayColor) {
            mOverlayColor = ta.getColor(attr, DEFAULT_COLOR);
        } else if (attr == R.styleable.WScratchView_revealSize) {
            mRevealSize = ta.getDimensionPixelSize(attr, DEFAULT_REVEAL_SIZE);
        } else if (attr == R.styleable.WScratchView_antiAlias) {
            mIsAntiAlias = ta.getBoolean(attr, false);
        } else if (attr == R.styleable.WScratchView_scratchable) {
            mIsScratchable = ta.getBoolean(attr, true);
        } else if (attr == R.styleable.WScratchView_scratchDrawable) {
            mScratchDrawable = ta.getDrawable(R.styleable.WScratchView_scratchDrawable);
        }
    }

    setZOrderOnTop(true);
    SurfaceHolder holder = getHolder();
    holder.addCallback(this);
    holder.setFormat(PixelFormat.TRANSPARENT);

    mOverlayPaint = new Paint();
    mOverlayPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
    mOverlayPaint.setStyle(Paint.Style.STROKE);
    mOverlayPaint.setStrokeCap(Paint.Cap.ROUND);
    mOverlayPaint.setStrokeJoin(Paint.Join.ROUND);

    // convert drawable to bitmap if drawable already set in xml
    if (mScratchDrawable != null) {
        mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap();
    }

    mBitmapPaint = new Paint();
    mBitmapPaint.setAntiAlias(true);
    mBitmapPaint.setFilterBitmap(true);
    mBitmapPaint.setDither(true);
}

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

    //Clear all area if mClearCanvas is true
    if(mClearCanvas){
        canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
        return;
    }

    if (mScratchBitmap != null) {
        if (mMatrix == null) {
            float scaleWidth = (float) canvas.getWidth() / mScratchBitmap.getWidth();
            float scaleHeight = (float) canvas.getHeight() / mScratchBitmap.getHeight();
            mMatrix = new Matrix();
            mMatrix.postScale(scaleWidth, scaleHeight);
        }
        canvas.drawBitmap(mScratchBitmap, mMatrix, mBitmapPaint);
    } else {
        canvas.drawColor(mOverlayColor);
    }

    for (Path path : mPathList) {
        mOverlayPaint.setAntiAlias(mIsAntiAlias);
        mOverlayPaint.setStrokeWidth(mRevealSize);

        canvas.drawPath(path, mOverlayPaint);
    }


}

private void updateScratchedPercentage() {
    if(mOnScratchCallback == null) return;
    mOnScratchCallback.onScratch(getScratchedRatio());
}

@Override
public boolean onTouchEvent(MotionEvent me) {
    synchronized (mThread.getSurfaceHolder()) {
        if (!mIsScratchable) {
            return true;
        }

        switch (me.getAction()) {
        case MotionEvent.ACTION_DOWN:
            path = new Path();
            path.moveTo(me.getX(), me.getY());
            startX = me.getX();
            startY = me.getY();
            mPathList.add(path);
            break;
        case MotionEvent.ACTION_MOVE:
            if (mScratchStart) {
                path.lineTo(me.getX(), me.getY());
            } else {
                if (isScratch(startX, me.getX(), startY, me.getY())) {
                    mScratchStart = true;
                    path.lineTo(me.getX(), me.getY());
                }
            }
            updateScratchedPercentage();
            break;
        case MotionEvent.ACTION_UP:
            //Set call back if user's finger detach
            if(mOnScratchCallback != null){
                    mOnScratchCallback.onDetach(true);  
            }
            //perform Click action if the motion is not move
            //and the WScratchView is clickable
            if(!mScratchStart && mIsClickable){
                post(new Runnable() {
                    @Override
                    public void run() {
                        performClick();
                    }
                });
            }
            mScratchStart = false;
            break;
        }
        return true;
    }
}

private boolean isScratch(float oldX, float x, float oldY, float y) {
    float distance = (float) Math.sqrt(Math.pow(oldX - x, 2) + Math.pow(oldY - y, 2));
    if (distance > mRevealSize * 2) {
        return true;
    } else {
        return false;
    }
}

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    // do nothing
}

@Override
public void surfaceCreated(SurfaceHolder arg0) {
    mThread = new WScratchViewThread(getHolder(), this);
    mThread.setRunning(true);
    mThread.start();

    mScratchedTestBitmap = Bitmap.createBitmap(arg0.getSurfaceFrame().width(), arg0.getSurfaceFrame().height(), Bitmap.Config.ARGB_8888);
    mScratchedTestCanvas = new Canvas(mScratchedTestBitmap);
}

@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
    boolean retry = true;
    mThread.setRunning(false);
    while (retry) {
        try {
            mThread.join();
            retry = false;
        } catch (InterruptedException e) {
            // do nothing but keep retry
        }
    }

}

class WScratchViewThread extends Thread {
    private SurfaceHolder mSurfaceHolder;
    private WScratchView mView;
    private boolean mRun = false;

    public WScratchViewThread(SurfaceHolder surfaceHolder, WScratchView view) {
        mSurfaceHolder = surfaceHolder;
        mView = view;
    }

    public void setRunning(boolean run) {
        mRun = run;
    }

    public SurfaceHolder getSurfaceHolder() {
        return mSurfaceHolder;
    }

    @Override
    public void run() {
        Canvas c;
        while (mRun) {
            c = null;
            try {
                c = mSurfaceHolder.lockCanvas(null);
                synchronized (mSurfaceHolder) {
                    if (c != null) {
                        mView.draw(c);
                    }
                }
            } finally {
                if (c != null) {
                    mSurfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

@Override
public void resetView() {
    synchronized (mThread.getSurfaceHolder()) {
        mPathList.clear();
    }
}

@Override
public boolean isScratchable() 
{
    return mIsScratchable;
}

@Override
public void setScratchable(boolean flag) {
    mIsScratchable = flag;
}

@Override
public void setOverlayColor(int ResId) {
    mOverlayColor = ResId;
}

@Override
public void setRevealSize(int size) {
    mRevealSize = size;
}

@Override
public void setAntiAlias(boolean flag) {
    mIsAntiAlias = flag;
}


@Override
public void setScratchDrawable(Drawable d) {
    mScratchDrawable = d;
    if (mScratchDrawable != null) {
        mScratchBitmap = ((BitmapDrawable) mScratchDrawable).getBitmap();
    }
}

@Override
public void setScratchBitmap(Bitmap b) {
    mScratchBitmap = b;
}


@Override
public float getScratchedRatio() {
    return getScratchedRatio(DEFAULT_SCRATCH_TEST_SPEED);
}

/**
 * thanks to https://github.com/daveyfong for providing this method
 */
@Override
public float getScratchedRatio(int speed) {
    if (null == mScratchedTestBitmap) {
        return 0;
    }
    draw(mScratchedTestCanvas);

    final int width = mScratchedTestBitmap.getWidth();
    final int height = mScratchedTestBitmap.getHeight();

    int count = 0;
    for (int i = 0; i < width; i += speed) {
        for (int j = 0; j < height; j += speed) {
            if (0 == Color.alpha(mScratchedTestBitmap.getPixel(i, j))) {
                count++;
            }
        }
    }
    float completed = (float) count / ((width / speed) * (height / speed)) * 100;

    return completed;
}

@Override
public void setOnScratchCallback(OnScratchCallback callback) {
    mOnScratchCallback = callback;
}

public static abstract class OnScratchCallback{
    public abstract void onScratch(float percentage);
    //Call back funtion to monitor the status of finger
    public abstract void onDetach(boolean fingerDetach);
}

//Set the mClearCanvas
@Override
public void setScratchAll(boolean scratchAll){
    mClearCanvas = scratchAll;
}

//Set the WScartchView clickable
@Override
public void setBackgroundClickable(boolean clickable){
    mIsClickable = clickable;
}

}

,位图代码如下

 gray.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // TODO Auto-generated method stub
            FrameLayout fm = (FrameLayout)findViewById(R.id.frmQueue);
            fm.setDrawingCacheEnabled(true);
            fm.buildDrawingCache();
            Bitmap bm =fm.getDrawingCache();

            scratchView.setScratchBitmap(bm);

1 个答案:

答案 0 :(得分:0)

你可以试试这段代码吗

 public Bitmap loadBitmapFromView(View v, int width, int height) {
    Bitmap b = Bitmap.createBitmap(width , height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(b);
    v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
    v.draw(c);
    return b;
}

调用类似于

Bitmap imageBitmap = loadBitmapFromView(frameLayout, frameLayout.getLayoutParams().width,frameLayout.getLayoutParams().height));

您可以将此代码用于FrameLayout吗?

    FrameLayout view = (FrameLayout)findViewById(R.id.framelayout);
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    Bitmap bm = view.getDrawingCache();