【问题标题】:Implementing magnifier/loupe for custom dynamic view on android在android上为自定义动态视图实现放大镜/放大镜
【发布时间】:2015-12-01 23:44:07
【问题描述】:

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

【问题讨论】:

    标签: android view android-custom-view loupe


    【解决方案1】:

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

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

    【讨论】:

    • Thx,相当不错的变体,但有一些问题:-我在 grath 中绘制放大镜,并且延迟了 1 步-有时位图着色器缩放不正确-使用 onDraw 方法绘制的绘图视图可能会导致问题。抱歉,无法为你添加一些声望(
    【解决方案2】:

    我自己弄明白了。 所以这里是动态变化视图的变体。

    1) 首先,我们在 Overriden on Draw 方法中创建具有相同高度和宽度的新位图(整体);

    2) 从我们的位图(整体)创建 Canvas(temporalCanvas)

    3) 在 canvas(temporalCanvas) 上绘制我们需要的一切

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

    5) 从 MotionEvent 获取坐标(它应该在 ACTION_DOWN 上设为全局静态),因此这将是无效和绘制视图后的 SAME MotionEvent

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

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

    可能的困难: -Motion 事件在从覆盖的 onTouchEvent 或从 ACTION_DOWN 上进行的静态事件调用时返回不同的坐标 X、Y; (只需将 x,y 坐标设为静态)并且不要忘记删除静态触摸事件,以及动作 UP 上的 x,y 坐标

    应该使用-2画布或者你可以放大镜放大镜)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-21
      • 2010-10-27
      • 1970-01-01
      • 2011-09-14
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多