Zoomlayout: انقر نقرًا مزدوجًا للتكبير

تم إنشاؤها على ٢٩ سبتمبر ٢٠١٧  ·  13تعليقات  ·  مصدر: natario1/ZoomLayout

من الشائع أن تتفاعل مع النقرات المزدوجة للتحكم في التكبير / التصغير. يجب أن تكون هذه ميزة اشتراك في ZoomEngine ، يتم تمكينها افتراضيًا في ZoomImageView .

enhancement long term

التعليق الأكثر فائدة

مرحبا،

أي أخبار عن كيفية تحقيق التكبير + التحريك بنقرة مزدوجة؟

شكرا،
كريستوف

ال 13 كومينتر

@ natario1

في الوقت الحالي ، قمت للتو بتنفيذ هذه الوظيفة بنفسي باستخدام فئة Gesture Listener المخصصة. إليك مقتطف الشفرة الخاص بي إذا احتاجه أي شخص.

private GestureDetector gestureDetector; 
private View.OnTouchListener touchListener;
private ZoomImageView selectedImage;

ثم قم بتهيئة هذه المتغيرات:

    gestureDetector = new GestureDetector(mContext, new MyGestureListener());

        touchListener = new View.OnTouchListener() {
            <strong i="11">@Override</strong>
            public boolean onTouch(View v, MotionEvent event) {
                // pass the events to the gesture detector
                // a return value of true means the detector is handling it
                // a return value of false means the detector didn't
                // recognize the event
                selectedImage = (ZoomImageView) v;
                return gestureDetector.onTouchEvent(event);

            }
        };

ثم قم بتعيين مستمع اللمس الخاص بك إلى كائن Zoomimageview:

    ZoomImageView image = layout.findViewById(R.id.imageViewItemImageSlider);
    image.setOnTouchListener(touchListener);

وهنا فئة MyGestureListener:

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

//        <strong i="18">@Override</strong>
//        public boolean onDown(MotionEvent event) {
//            Log.d("TAG","onDown: ");
//
//            // don't return false here or else none of the other
//            // gestures will work
//            return true;
//        }
//
//        <strong i="19">@Override</strong>
//        public boolean onSingleTapConfirmed(MotionEvent e) {
//            Log.i("TAG", "onSingleTapConfirmed: ");
//            return true;
//        }
//
//        <strong i="20">@Override</strong>
//        public void onLongPress(MotionEvent e) {
//            Log.i("TAG", "onLongPress: ");
//        }

        <strong i="21">@Override</strong>
        public boolean onDoubleTap(MotionEvent e) {
            Log.i("TAG", "onDoubleTap: ");
            if((selectedImage.getEngine().getZoom() >= 2.75F)) {
                selectedImage.getEngine().zoomTo(1F, true);
            } else if((selectedImage.getEngine().getZoom() < 1F)) {
                selectedImage.getEngine().zoomTo(1F, true);
            }  else {
                selectedImage.getEngine().zoomBy(2F, true);
            }

            return true;
        }

//        <strong i="22">@Override</strong>
//        public boolean onScroll(MotionEvent e1, MotionEvent e2,
//                                float distanceX, float distanceY) {
//            Log.i("TAG", "onScroll: ");
//            return true;
//        }

//        <strong i="23">@Override</strong>
//        public boolean onFling(MotionEvent event1, MotionEvent event2,
//                               float velocityX, float velocityY) {
//            Log.d("TAG", "onFling: ");
//            return true;
//        }
    }

يرجى القيام بتجاوز onScroll (MUST) والطريقة الأخرى (اختيارية في حالتي) والتي ليس لديك أي شيء للتعامل معها لأنها ستتعارض مع حدث اللمس الخاص بـ ZoomImageView وستنشئ مشكلة.

ارجوا ان يساعدك هذا.

أنا أتفاعل حاليًا مع النقر المزدوج لتوسيط الشاشة حيث تم الحدث.

ببساطة عن طريق إضافة هذا:

    private val simpleGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {


        //here is the method for double tap


        override fun onDoubleTap(e: MotionEvent): Boolean {

            Log.d("OnDoubleTapListener", "onDoubleTap")
            centerElement(e.x.absoluteValue,e.y.absoluteValue)
            return true
        }

    })

    fun centerElement(clickedX: Float, clickedY: Float) {
        val offsetX = (width.absoluteValue) / 2
        val offsetY = (height.absoluteValue) / 2
        val displacedX = engine.panX.absoluteValue
        val displacedY = engine.panY.absoluteValue
        val x = (displacedX + clickedX / engine.realZoom) - (offsetX / engine.realZoom)
        val y = (displacedY + clickedY / engine.realZoom) - (offsetY / engine.realZoom)
        val desiredX = if (x > 0) -x else 0f
        val desiredY = if (y > 0) -y else 0f
        engine.moveTo(engine.zoom, desiredX, desiredY, true)
    }

الآن أحاول التحرك والتكبير بشكل صحيح. يمكنني فتح طلب سحب إذا كنت تريد إنجاحه.

AlvaroFalcon هذا سيكون رائعًا! أستطيع أن أعطيك بعض النصائح.

  • لدينا بالفعل كاشف إيماءات في ZoomEngine يتفاعل مع التمرير والقذف
  • أعتقد أنه يمكنك إعادة استخدام 99٪ من المنطق داخل onScale() . إنه يعمل مع إحداثيات مركز إيماءة المقياس ويطبق عامل التكبير / التصغير. سيتعين عليك تعيين عامل تكبير / تصغير بنفسك (أعتقد أن zoomIn() يستخدم 1.3) لكنها نفس المهمة تقريبًا
  • يجب أن يكون هذا قابلاً للتكوين من خلال سمة XML ( doubleTapBehavior ؟) والتي يجب أن تحتوي على خيارين على الأقل ("بلا" و "تكبير"). دعنا لا نستخدم أيًا كإعداد افتراضي حتى لا نغير هذا لمن يستخدم lib بالفعل.

@ natario1 رائع! سأفعل ذلك عندما يكون لدي بعض الوقت ...

أنا أعمل حاليًا في مشروعي مع فصل يعمل على توسيع نطاق التكبير حتى أقوم بإضافة منطقتي هناك.
أحاول التكبير بالحركة في نفس الوقت باستخدام ذلك ، لكن لا حظ في الوقت الحالي.

شكرا على النصائح!

هل يمكن إضافة إجراء في طريقة moveTo ()؟ ليتم استدعاؤك بعد انتهائها ، أعتقد أنه سيكون أكثر مرونة بهذه الطريقة حتى تتمكن من القيام بأشياء متعددة.

حسنًا ، للتحرك إلى ، تكبير / تصغير ، تكبير / تصغير ، إلخ ...

يمكن أن يكون مثل:

moveTo(zoom, x, y, action : ()->Unit={})

AlvaroFalcon في Kotlin سأفعل ذلك ولكن هذا لا يزال جافا خالصًا. ومع ذلك ، سوف ننتقل إلى Kotlin في المستقبل. في الوقت الحالي ، هناك onIdle() يمكن لأي شخص الوصول إليه.

AlvaroFalcon هل تمكنت من تحقيق التكبير والتصغير في نفس الوقت؟ تمانع في مشاركة التعليمات البرمجية الخاصة بك؟

لقد قمت بتنفيذ كل من النقر المزدوج والقرص للتكبير. مفتاح حل العمل هو إرفاق كاشف إيماءات النقر / النقر المزدوج بعرض المحتوى داخل تخطيط التكبير / التصغير وتكوين تخطيط التكبير / التصغير لجعل الأطفال قابلين للنقر على صواب. ثم في onTouchEvent لعرض المحتوى ، ارجع بشكل صحيح لاستهلاك أحداث اللمس وتمريرها إلى كاشف الإيماءات. بهذه الطريقة يعمل كل من القرص والتكبير والنقر المزدوج في نفس الوقت. لا يمثل التكبير عند النقر المزدوج مشكلة بعد ذلك.

ومع ذلك ، فقد حاولت أيضًا تكبير المنطقة التي تم النقر عليها مرتين ، وبالنظر إلى كيفية تنفيذ ZoomEngine.moveTo ، فإن الاستيفاء المتزامن للتكبير والتصغير لا يتصرف بشكل صحيح وتتحرك الصورة حول مسارات مختلفة للوصول إلى تكبير الوجهة وعموم. لا يبدو الأمر ممتعًا بصريًا ، لكنني غير قادر على معرفة ما يحدث. أعتقد أن خوارزمية الاستيفاء يجب أن تحسب بشكل مختلف عمومًا الفعلي بناءً على ما هو التكبير الفعلي ، وليس فقط جزء من الرسوم المتحركة.

تكبير المنطقة التي تم النقر عليها مرتين

نعم ، هذا بالضبط ما كنت أحاول القيام به. أي اقتراحات حول كيفية القيام بذلك @ natario1؟

مرحبًا mman

لقد قمنا أيضًا بتطبيق طريقة للتكبير تلقائيًا عندما ينقر المستخدم على الشاشة والرسوم المتحركة للتكبير نوعًا من الدوران نحو الموضع النهائي.

سيكون من الجيد جدًا ، إذا تمكنا من التحكم في هذه الرسوم المتحركة - هل لديك أو لدى الآخرين اقتراحات حول كيفية القيام بذلك؟

شكرا لك مقدما :)

تمكنت من القيام بذلك مع اختراق قذر. إنني أخدع محرك الزوم لأفكر في حدوث ضغط.

class ReflectionHelper {
    <strong i="6">@Nullable</strong>
    static ScaleGestureDetector.OnScaleGestureListener getScaleDetectorListenerUsingReflection(ZoomEngine zoomEngine) {
        try {
            Field mScaleDetector = zoomEngine.getClass().getDeclaredField("mScaleDetector");
            mScaleDetector.setAccessible(true);
            ScaleGestureDetector detector = (ScaleGestureDetector) mScaleDetector.get(zoomEngine);
            Field mListener = detector.getClass().getDeclaredField("mListener");
            mListener.setAccessible(true);
            return (ScaleGestureDetector.OnScaleGestureListener) mListener.get(detector);
        } catch (Exception e) {
            return null;
        }
    }
}

private fun simulatePinch(fromScale: Float, toScale: Float, focusX: Float, focusY: Float) {
    class MockDetector(var mockScaleFactor: Float, var mockFocusX: Float, var mockFocusY: Float) : ScaleGestureDetector(context, null) {
        override fun getScaleFactor() = mockScaleFactor
        override fun getFocusX() = mockFocusX
        override fun getFocusY() = mockFocusY
    }

    val mockDetector = MockDetector(fromScale, focusX, focusY)
    ValueAnimator.ofFloat(fromScale, toScale).apply {
        addUpdateListener { animation ->
            mockDetector.mockScaleFactor = animation.animatedValue as Float
            zoomEngineScaleListener?.onScale(mockDetector)
        }
        doOnEnd { zoomEngineScaleListener?.onScaleEnd(mockDetector) }
        start()
    }
}

مرحبا،

شكرا لهذا الجهد! :)

هذا بالتأكيد يبدو وكأنه طريقة مبتذلة لتحقيق ذلك. أعتقد أننا سنختار العيش مع الرسوم المتحركة للغاية في الوقت الحالي.

شكرا،
نيكولاج

مرحبا،

أي أخبار عن كيفية تحقيق التكبير + التحريك بنقرة مزدوجة؟

شكرا،
كريستوف

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

kuoliangkwong picture kuoliangkwong  ·  4تعليقات

YiHaoHuang picture YiHaoHuang  ·  10تعليقات

wakaztahir picture wakaztahir  ·  5تعليقات

MohamedMedhat1998 picture MohamedMedhat1998  ·  6تعليقات

aouledissa picture aouledissa  ·  10تعليقات