更新工作-如何通过在Android触摸屏上滑动手指来测试智能手机屏幕?

时间:2019-10-21 08:27:15

标签: java android screen touchscreen

我正在制作一个移动电子商务应用程序,该应用程序通过在屏幕上拖动或滑动以测试屏幕是否损坏来测试用户的移动屏幕状况。

我添加了一个图像,供用户在拖动时在屏幕上跟随。 我添加了工作代码,但是当用户跟随​​这条线时它有点慢,它将这条线擦除得很慢,但是我正在通过这种方法或其他方法来寻找某种速度。 我遵循了许多教程,但没有获得相关代码。

注意:也可以使用另一种测试屏幕的方法。

感谢您的答复。

enter image description here

----------我将此代码放入Activity ------------

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.screentest_img);

        imageToErase.setScratchBitmap(bitmap);

        imageToErase.setOnScratchCallback(new WScratchView.OnScratchCallback() {
            @Override
            public void onScratch(float percentage) {
                updatePercentage(percentage);
            }

            @Override
            public void onDetach(boolean fingerDetach) {
                if (mPercentage > 99) {
                    imageToErase.setScratchAll(true);
                    updatePercentage(100);
                }
            }
        });

---------------另一种方法---------------

 private void updatePercentage(float percentage) {

        mPercentage = percentage;

        if(percentage > 99){
            Toast.makeText(context, "Screen Condition is good "+percentage, Toast.LENGTH_SHORT).show();
        }

    }

---------- WScratchView类----------------------

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import org.geniusmindsystem.digify_design.R;

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

/**
 * This view start with full gray color bitmap and onTouch to make it
 * transparent
 * 
 * @author winsontan520
 */
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
    private final int DEFAULT_REVEAL_SIZE = 90;

    public static final int DEFAULT_SCRATCH_TEST_SPEED = 4;

    private Context mContext;
    private WScratchViewThread mThread;
    List<Path> mPathList = new ArrayList<Path>();
    private int mOverlayColor;
    private Paint mOverlayPaint;
    private 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;
    private Bitmap mScratchBitmap;
    private Drawable mScratchDrawable = null;
    private Paint mBitmapPaint;
    private Matrix mMatrix;
    private Bitmap mScratchedTestBitmap;
    private 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);
            switch (attr) {
            case R.styleable.WScratchView_overlayColor:
                mOverlayColor = ta.getColor(attr, DEFAULT_COLOR);
                break;
            case R.styleable.WScratchView_revealSize:
                mRevealSize = ta.getDimensionPixelSize(attr, DEFAULT_REVEAL_SIZE);
                break;
            case R.styleable.WScratchView_antiAlias:
                mIsAntiAlias = ta.getBoolean(attr, false);
                break;
            case R.styleable.WScratchView_scratchable:
                mIsScratchable = ta.getBoolean(attr, true);
                break;
            case R.styleable.WScratchView_scratchDrawable:
                mScratchDrawable = ta.getDrawable(R.styleable.WScratchView_scratchDrawable);
                break;
            }
        }

        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;
    }
}

--------------接口IWScratchView ---------------

import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;


public interface IWScratchView {

    /**
     * Whether the view receive user on touch motion
     * 
     * @return true if scratchable
     */
    public boolean isScratchable();

    /**
     * If true, set the view allow receive on touch to reveal the view
     * By default, scratchable is true
     * 
     * @param flag - flag for enable/disable scratch
     */
    public void setScratchable(boolean flag);

    /**
     * Set the color of overlay
     * 
     * @param ResId - resources identifier for color in INT type
     */
    public void setOverlayColor(int ResId);

    /**
     * Set the radius size of the circle to be revealed
     * 
     * @param size - radius size of circle in pixel unit
     */
    public void setRevealSize(int size);

    /**
     * Set turn on/off effect of anti alias of circle revealed
     * By default, anti alias is turn off
     * 
     * @param flag - set true to turn on anti alias
     */
    public void setAntiAlias(boolean flag);

    /**
     * Reset the scratch view
     * 
     */
    public void resetView();

    /**
     * Set drawable for scratch view
     * 
     * @param drawable - Set drawable for scratch view
     */
    public void setScratchDrawable(Drawable drawable);

    /**
     * Set bitmap for scratch view
     * 
     * @param -bitmap - Set bitmap for scratch view
     */
    public void setScratchBitmap(Bitmap b);

    /**
     * Get scratched ratio (contribution from daveyfong)
     * 
     * @return  float - return Scratched ratio
     */
    public float getScratchedRatio();

    /**
     * Get scratched ratio (contribution from daveyfong)
     * 
     * @param -int - Scratch speed
     * @return  float - return Scratched ratio
     */
    public float getScratchedRatio(int speed);

    public void setOnScratchCallback(WScratchView.OnScratchCallback callback);

    public void setScratchAll(boolean scratchAll);

    public void setBackgroundClickable(boolean clickable);
}

--------以XML格式------

<org.geniusmindsystem.digify_design.Retailer.WScratchView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:adjustViewBounds="true"
        android:scaleType="centerInside"
        android:id="@+id/image_to_erase"/>

------------- UPDATE _____________________-

just increase the number of variable (DEFAULT_SCRATCH_TEST_SPEED) in WScratchView class ....it will increase the speed of erasing line.

1 个答案:

答案 0 :(得分:0)

如果您正在寻找一个框架来测试您的应用e2e的行为并记录用户场景的行为,我建议您使用https://github.com/wix/Detox

祝你好运!