Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在android上实现自定义动态视图的放大镜/放大镜_Android_View_Android Custom View_Loupe - Fatal编程技术网

在android上实现自定义动态视图的放大镜/放大镜

在android上实现自定义动态视图的放大镜/放大镜,android,view,android-custom-view,loupe,Android,View,Android Custom View,Loupe,我正在寻找一种在android上为自定义视图实现放大镜/放大镜的方法,它正在动态重建。我创建这个类只是为了回答您的问题。这是放大镜最基本的实现,希望对大家有所帮助。祝你好运: public class ExampleMagnifierView extends View { Matrix matrix = new Matrix(); Paint shaderPaint = new Paint(); BitmapShader shader = null; //start the magnifier

我正在寻找一种在android上为自定义视图实现放大镜/放大镜的方法,它正在动态重建。

我创建这个类只是为了回答您的问题。这是放大镜最基本的实现,希望对大家有所帮助。祝你好运:

public class ExampleMagnifierView extends View {

Matrix matrix = new Matrix();
Paint shaderPaint = new Paint();
BitmapShader shader = null;
//start the magnifier
boolean zooming;
//capture a new bitmap form a view
boolean isFirstTouch = true;
//magnifier position
static final PointF zoomPos = new PointF(0, 0);

private float magnifierSize = 75;
private Context context = null;
private Bitmap someBitmap = null;

ArrayList<Element> elements = new ArrayList<Element>();

public ExampleMagnifierView(Context context, AttributeSet attrs) {
    super(context, attrs);

    this.context = context;

    //Just for the example
    someBitmap = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_delete);

    //Just for the example
    elements = prepareElementsMatrix(5, 6);
}

@Override
protected void onDraw(Canvas canvas) {

    drawSomethingToBeMagnifiedNoMatterWhat(canvas);

    if (zooming) {
        matrix.reset();
        matrix.postScale(2f, 2f, zoomPos.x, zoomPos.y);
        shaderPaint.getShader().setLocalMatrix(matrix);
        canvas.drawCircle(zoomPos.x, zoomPos.y, convertDpToPixel(magnifierSize, this.getContext()), shaderPaint);
    }

}

private void drawSomethingToBeMagnifiedNoMatterWhat(Canvas canvas){

    for (Element el : elements){
        canvas.drawBitmap(someBitmap, el.x , el.y , null);
    }

}

@Override
public boolean onTouchEvent(MotionEvent event) {

    if (isFirstTouch) {
        //we set the zooming to false because we want a image of the view without magnifier
        zooming = false;

        shader = null;
        shaderPaint = null;
        shaderPaint = new Paint();

        //get a fresh bitmap from the view
        shader = new BitmapShader(getBitmapFromView(this), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        isFirstTouch = false;
    }

    shaderPaint.setShader(shader);
    matrix.reset();
    matrix.postTranslate(-zoomPos.x, -zoomPos.y - convertDpToPixel(magnifierSize, context));
    shader.setLocalMatrix(matrix);

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            zoomPos.x = event.getX();
            zoomPos.y = event.getY() - convertDpToPixel(magnifierSize, context);

            //this flag starts drawing the magnifier
            zooming = true;
            invalidate();

            isFirstTouch = true;


            break;
        case MotionEvent.ACTION_MOVE:

            zoomPos.x = event.getX();
            zoomPos.y = event.getY() - convertDpToPixel(magnifierSize, context);

            //this flag starts drawing the magnifier
            zooming = true;
            invalidate();

            break;

        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:

            isFirstTouch = true;
            zooming = false;
            invalidate();

            break;
    }

    return true;

}

/**
 * This method get the bitmap form a view.
 *
 * @param view The view who we want as a bitmap
 * @return The view's bitmap
 */
public static Bitmap getBitmapFromView(View view) {
    //Define a bitmap with the same size as the view ( Use RGB_565 for better performance )
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.RGB_565);
    //Bind a canvas to it
    Canvas canvas = new Canvas(returnedBitmap);
    //Get the view's background
    Drawable bgDrawable = view.getBackground();
    if (bgDrawable != null) {
        //has background drawable, then draw it on the canvas
        bgDrawable.draw(canvas);
    } else {
        //does not have background drawable, then draw white background on the canvas
        canvas.drawColor(Color.WHITE);
    }
    // draw the view on the canvas
    view.draw(canvas);

    //erase the drawable
    bgDrawable = null;

    //return the bitmap
    return returnedBitmap;
}

/**
 * This method converts dp unit to equivalent pixels, depending on device density.
 *
 * @param dp      A value in dp (density independent pixels) unit. Which we need to convert into pixels
 * @param context Context to get resources and device specific display metrics
 * @return A float value to represent px equivalent to dp depending on device density
 */
public static float convertDpToPixel(float dp, Context context) {
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return px;
}

private ArrayList<Element> prepareElementsMatrix(int rows, int columns){
    ArrayList<Element> elementsMatrix = new ArrayList<Element>();
    int offsetX = 0;
    int offsetY = 0;

    for (int i = 0; i<=columns; i++){

        offsetX += someBitmap.getWidth() + 5;
        elementsMatrix.add(new Element(offsetX, offsetY));
        for (int j = 0; j<=rows; j++){
            elementsMatrix.add(new Element(offsetX, offsetY));
            offsetY += someBitmap.getHeight() + 5;
        }

        offsetY = 0;
    }

    return elementsMatrix;
}

private class Element{
    int x;
    int y;

    public Element(int x, int y){
        this.x = x;
        this.y = y;
    }

}
公共类示例放大镜视图扩展视图{
矩阵=新矩阵();
Paint shaderPaint=新绘制();
BitmapShader=null;
//启动放大镜
布尔缩放;
//从视图中捕获新位图
布尔值isFirstTouch=true;
//放大镜位置
静态最终点f zoomPos=新点f(0,0);
专用浮点放大镜尺寸=75;
私有上下文=null;
私有位图someBitmap=null;
ArrayList元素=新的ArrayList();
公共示例放大镜视图(上下文、属性集属性){
超级(上下文,attrs);
this.context=上下文;
//举个例子
someBitmap=BitmapFactory.decodeResource(getResources(),android.R.drawable.ic_delete);
//举个例子
元素=准备元素矩阵(5,6);
}
@凌驾
受保护的void onDraw(画布){
画一些东西来象征什么(画布);
如果(缩放){
matrix.reset();
postScale(2f,2f,zoomPos.x,zoomPos.y);
shaderPaint.getShader().setLocalMatrix(矩阵);
drawCircle(zoomPos.x,zoomPos.y,convertDpToPixel(放大镜大小,this.getContext()),shaderPaint);
}
}
私人虚空绘制一些东西来装饰一些东西(帆布){
用于(元素el:元素){
drawBitmap(someBitmap,el.x,el.y,null);
}
}
@凌驾
公共布尔onTouchEvent(运动事件){
如果(isFirstTouch){
//我们将缩放设置为false,因为我们想要的是没有放大镜的视图图像
缩放=假;
着色器=空;
shaderPaint=空;
shaderPaint=新绘制();
//从视图中获取新位图
着色器=新的位图着色器(getBitmapFromView(this),shader.TileMode.CLAMP,shader.TileMode.CLAMP);
isFirstTouch=false;
}
shaderPaint.setShader(着色器);
matrix.reset();
postTranslate(-zoomPos.x,-zoomPos.y-convertDpToPixel(放大镜大小,上下文));
setLocalMatrix(矩阵);
开关(event.getAction()){
case MotionEvent.ACTION\u DOWN:
zoomPos.x=event.getX();
y=event.getY()-convertDpToPixel(放大镜大小,上下文);
//此标志开始绘制放大镜
缩放=真;
使无效();
isFirstTouch=true;
打破
case MotionEvent.ACTION\u移动:
zoomPos.x=event.getX();
y=event.getY()-convertDpToPixel(放大镜大小,上下文);
//此标志开始绘制放大镜
缩放=真;
使无效();
打破
case MotionEvent.ACTION\u UP:
case MotionEvent.ACTION\u取消:
isFirstTouch=true;
缩放=假;
使无效();
打破
}
返回true;
}
/**
*此方法从视图中获取位图。
*
*@param以位图的形式查看我们想要的用户
*@返回视图的位图
*/
公共静态位图getBitmapFromView(视图){
//定义与视图大小相同的位图(使用RGB_565可获得更好的性能)
Bitmap returnedBitmap=Bitmap.createBitmap(view.getWidth()、view.getHeight()、Bitmap.Config.RGB_565);
//把画布绑在上面
画布画布=新画布(返回的位图);
//获取视图的背景
Drawable-bgDrawable=view.getBackground();
如果(bgDrawable!=null){
//背景可绘制,然后在画布上绘制
bgDrawable.draw(画布);
}否则{
//没有可绘制的背景,然后在画布上绘制白色背景
画布。drawColor(颜色。白色);
}
//在画布上绘制视图
视图.绘制(画布);
//删除可绘制的
bgDrawable=null;
//返回位图
返回位图;
}
/**
*此方法根据设备密度将dp单位转换为等效像素。
*
*@param dp以dp(密度无关像素)为单位的值。我们需要将其转换为像素
*@param上下文用于获取资源和设备特定的显示度量
*@根据设备密度返回一个浮点值,表示px等于dp
*/
公共静态浮点convertDpToPixel(浮点dp,上下文){
Resources=context.getResources();
DisplayMetrics=resources.getDisplayMetrics();
浮点数px=dp*(公制密度dpi/160f);
返回px;
}
private ArrayList prepareElementsMatrix(int行、int列){
ArrayList elementsMatrix=新的ArrayList();
int offsetX=0;
int offsetY=0;

对于(inti=0;i,我自己已经解决了。 这里是动态变化视图的变体

1) 首先,我们在重写绘制方法中创建具有相同高度和宽度的新位图(整体)

2) 从位图(整体)创建画布(临时画布)

3) 在画布上绘制我们需要的一切(临时画布)

4) 将位图绘制到onDraw收入中给出的原始画布(画布)

5) 从MotionEvent获取坐标(在ACTION_DOWN时应使其成为全局静态),以便在无效和工程视图后,这将是相同的MotionEvent

6) 围绕选定(MotionEvent.GetX/Y)位置剪切位图

7) 在原始(画布)画布上绘制修剪过的位图

可能的困难: -当从重写的onTouchEvent或从静态事件调用运动事件时,运动事件返回不同的坐标X,Y,其中在ACTION_DOWN上进行;(只需使X,Y坐标为静态)并且不要忘记移除静态触摸事件,以及在ACTION UP上的X,Y坐标


-2应使用帆布或您可以使用放大镜(放大镜)

Thx,相当不错的变体,但有一些问题:-我在g中绘制放大镜