Zoomlayout: Ketuk dua kali untuk memperbesar

Dibuat pada 29 Sep 2017  ·  13Komentar  ·  Sumber: natario1/ZoomLayout

Adalah umum untuk bereaksi terhadap ketukan dua kali untuk mengontrol zoom. Ini harus menjadi fitur keikutsertaan di ZoomEngine , diaktifkan secara default di ZoomImageView .

enhancement long term

Komentar yang paling membantu

Hai,

Adakah berita tentang cara mencapai zooming + panning dengan ketuk dua kali?

Terima kasih,
Christophe

Semua 13 komentar

@natari1

Untuk saat ini, saya baru saja mengimplementasikan fungsi ini sendiri dengan kelas Pendengar Gerakan khusus. Ini cuplikan kode saya jika ada yang membutuhkannya.

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

kemudian inisialisasi variabel-variabel ini:

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

            }
        };

lalu tetapkan pendengar sentuh Anda ke objek zoomimageview:

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

dan inilah kelas 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;
//        }
    }

Harap lakukan override onScroll (HARUS) dan metode lain (Opsional dalam kasus saya) yang tidak perlu Anda tangani karena akan bertentangan dengan acara sentuh ZoomImageView dan membuat masalah.

Semoga ini bisa membantu Anda.

Saat ini saya bereaksi terhadap ketuk dua kali untuk memusatkan layar tempat acara selesai.

Cukup dengan menambahkan ini:

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

Sekarang saya mencoba untuk bergerak dan memperbesar dengan benar. Saya dapat membuka permintaan tarik jika Anda ingin membuatnya berfungsi.

@AlvaroFalcon itu keren! Saya bisa memberi Anda beberapa tips.

  • Kami sudah memiliki detektor gerakan di ZoomEngine yang bereaksi terhadap gulir dan lempar
  • Saya pikir Anda dapat menggunakan kembali 99% logika di dalam onScale() . Ia bekerja dengan koordinat pusat gerakan skala dan menerapkan faktor zoom. Anda harus menetapkan faktor zoom sendiri (saya pikir zoomIn() menggunakan 1.3) tetapi itu adalah tugas yang hampir sama
  • Ini harus dapat dikonfigurasi melalui atribut XML ( doubleTapBehavior ?) yang harus memiliki setidaknya dua opsi ("tidak ada" dan "zoom"). Mari kita gunakan none sebagai default sehingga kita tidak mengubah ini untuk siapa yang sudah menggunakan lib.

@natari1 Keren! Saya akan melakukannya ketika saya punya waktu ...

Saat ini saya sedang mengerjakan proyek saya dengan kelas yang memperluas zoomlayout Anda, jadi saya menambahkan logika saya di sana.
Saya mencoba membuat zoom dengan gerakan pada saat yang sama menggunakan itu, tetapi tidak berhasil untuk saat ini.

Terima kasih untuk tipsnya!

Bisakah suatu tindakan ditambahkan dalam metode moveTo()? Dipanggil setelah selesai, saya pikir akan lebih fleksibel seperti itu sehingga Anda dapat melakukan banyak hal.

Nah, untuk moveTo, zoomBy, zoomTo, dll...

Itu bisa seperti:

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

@AlvaroFalcon Di Kotlin saya akan melakukan itu tetapi ini masih murni Java. Kami akan pindah ke Kotlin di masa depan. Untuk saat ini, ada onIdle() yang dapat diakses siapa saja.

@AlvaroFalcon apakah Anda dapat mencapai zoom dan menggeser secara bersamaan? keberatan berbagi kode Anda?

Saya telah menerapkan ketuk dua kali dan cubit untuk memperbesar. Kunci untuk solusi yang berfungsi adalah dengan melampirkan detektor gerakan ketuk/ketuk dua kali ke tampilan konten di dalam tata letak zoom dan konfigurasikan tata letak zoom agar turunan yang dapat diklik menjadi true. Kemudian di onTouchEvent dari tampilan konten, kembalikan true untuk menggunakan peristiwa sentuh dan meneruskannya ke pendeteksi gerakan. Dengan begitu, cubit, perbesar, dan ketuk dua kali berfungsi secara bersamaan. Memperbesar dengan ketuk dua kali tidak masalah.

Namun, saya juga telah mencoba memperbesar ke area yang diketuk dua kali, dan mengingat bagaimana ZoomEngine.moveTo diimplementasikan, interpolasi zoom dan pan secara simultan tidak berfungsi dengan benar dan gambar meluncur di sekitar jalur yang berbeda untuk mencapai zoom dan geser tujuan. Itu tidak terlihat menyenangkan secara visual, namun saya tidak dapat mengetahui apa yang terjadi. Saya pikir algoritme interpolasi harus menghitung secara berbeda pan sebenarnya berdasarkan pada apa zoom sebenarnya, bukan hanya sebagian kecil dari animasi.

perbesar ke area yang diketuk dua kali

Ya, itulah yang saya coba lakukan. Adakah saran tentang bagaimana melakukan ini @ natari1?

Hai @mman

Kami juga telah menerapkan cara untuk memperbesar secara otomatis ketika pengguna mengetuk layar dan animasi untuk memperbesar dalam bentuk berputar-putar menuju posisi akhir.

Akan sangat bagus, jika kita dapat mengontrol animasi ini - apakah Anda atau orang lain memiliki saran tentang cara melakukannya?

Terima kasih sebelumnya :)

Saya berhasil melakukannya dengan hack kotor. Saya menipu mesin zoom untuk berpikir bahwa ada sesuatu yang terjadi.

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()
    }
}

Hai,

Terima kasih atas usahanya! :)

Itu pasti tampak seperti sedikit cara hacky untuk mencapainya. Namun saya pikir kita akan memilih untuk hidup dengan animasi yang sangat menjiwai untuk saat ini.

Terima kasih,
Nikolaj

Hai,

Adakah berita tentang cara mencapai zooming + panning dengan ketuk dua kali?

Terima kasih,
Christophe

Apakah halaman ini membantu?
0 / 5 - 0 peringkat