Zoom, rotate and move inside an ImageView on Android

1

I am creating an image viewer, style as it takes android native, that lets expand the image, move for it, with the typical gestures:

  • Pinch to zoom
  • Double tap to zoom automatically
  • By having the expanded image you can move through it
  • When you touch a single touch, hide the ActionBar
  • Show full screen
  • Uploading images from the internet
asked by Webserveis 17.04.2017 в 22:54
source

1 answer

1

I leave my solution using several libraries

The source of the image is large resolution 8k

Glide for loading images remotely xuanimageview as a substitute of the Imageview, is the one that allows zoom, drag&pan y rotar con sistema magnético , to put the image vertically or horizontally

Add bookstores

compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.github.allenxuan:xuanimageview:0.4.0'

To intercept the touches I have created an extended custom component of xuaniImageView and add a callback when detecting singleTapConfirmed

import com.allenxuan.xuanyihuang.xuanimageview.XuanImageView;

interface MyGestureDetector {
    void onSingleTap();
}

public class PhotoImageView extends XuanImageView implements View.OnTouchListener, GestureDetector.OnGestureListener,
        GestureDetector.OnDoubleTapListener {

    GestureDetectorCompat mGestureDetector;

    private static final String TAG = PhotoImageView.class.getSimpleName() + "my";
    MyGestureDetector callback;

    public PhotoImageView(Context context) {
        super(context);
        init(context);
    }

    public PhotoImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PhotoImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mGestureDetector = new GestureDetectorCompat(context, this);
    }

    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        //Log.d(TAG, "onTouch: ");
        return mGestureDetector.onTouchEvent(motionEvent);
    }

    @Override
    public boolean onDown(MotionEvent motionEvent) {
        //Log.d(TAG, "onDown: ");
        return false;
    }

    @Override
    public void onShowPress(MotionEvent motionEvent) {
        //Log.d(TAG, "onShowPress: ");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {
        //Log.d(TAG, "onSingleTapUp: ");
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
        //Log.d(TAG, "onScroll: ");
        return false;
    }

    @Override
    public void onLongPress(MotionEvent motionEvent) {

    }


    @Override
    public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
        //Log.d(TAG, "onFling: ");
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent motionEvent) {
        this.mGestureDetector.onTouchEvent(motionEvent);
        return super.onTouchEvent(motionEvent);
    }


    @Override
    public boolean onDoubleTap(MotionEvent event) {
        //Log.i(TAG, "onDoubleTap: " + event.toString());
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent event) {
        //Log.d(TAG, "onDoubleTapEvent: " + event.toString());
        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        //Log.d(TAG, "onSingleTapConfirmed: " + event.toString());
        if (callback != null) callback.onSingleTap();
        return true;
    }

}

The layou.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:animateLayoutChanges="true"
    tools:context="com.webserveis.app.testtransitions.PhotoViewActivity">



    <com.webserveis.app.testtransitions.PhotoImageView
        android:id="@+id/iv_photo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/dummy_image"
        app:AutoRotateCategory="2" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="#88676767"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</FrameLayout>

And the code of MainActivity.java

public class PhotoViewActivity extends AppCompatActivity {

    private static final String TAG = PhotoViewActivity.class.getSimpleName();
    private ActionBar actionBar;
    private MyCountDownTimer countDownTimer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.i(TAG, "onCreate: ");

        setContentView(R.layout.activity_photo_view);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        actionBar = getSupportActionBar();
        toggleHideyBar();

        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        countDownTimer = new MyCountDownTimer(8 * 1000, 1 * 1000);
        countDownTimer.start();


        PhotoImageView ivPhoto = (PhotoImageView) findViewById(R.id.iv_photo);

        ivPhoto.callback = new MyGestureDetector() {
            public void onSingleTap() {
                // callback code goes here
                Log.d(TAG, "onSingleTap: ");

                if (actionBar.isShowing()) {
                    if (actionBar.isShowing()) actionBar.hide();
                    countDownTimer.cancel();
                } else {
                    actionBar.show();
                    countDownTimer.cancel();
                    countDownTimer.start();
                }

            }

        };


        Glide.with(this).load("http://sdeerwallpaper.com/Cool-Wallpapers/8k-wallpapers-high-quality-Is-Cool-Wallpapers.jpg").into(ivPhoto);


    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        countDownTimer.cancel();
    }

    private class MyCountDownTimer extends CountDownTimer {
        MyCountDownTimer(long startTime, long interval) {
            super(startTime, interval);
        }

        @Override
        public void onFinish() {
            //DO WHATEVER YOU WANT HERE
            Log.d(TAG, "MyCountDownTimer onFinish: ");
            if (getSupportActionBar() != null) {
                if (getSupportActionBar().isShowing()) {
                    getSupportActionBar().hide();
                    Log.i(TAG, "Hide ActionBar: ");
                }
            }
        }

        @Override
        public void onTick(long millisUntilFinished) {
            Log.d(TAG, "onTick: ");
        }

    }

    public void toggleHideyBar() {

        int uiOptions = getWindow().getDecorView().getSystemUiVisibility();
        int newUiOptions = uiOptions;
        boolean isImmersiveModeEnabled =
                ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions);
        if (isImmersiveModeEnabled) {
            Log.i(TAG, "Turning immersive mode mode off. ");
        } else {
            Log.i(TAG, "Turning immersive mode mode on.");
        }

        // Navigation bar hiding:  Backwards compatible to ICS.
        if (Build.VERSION.SDK_INT >= 14) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        }

        // Status bar hiding: Backwards compatible to Jellybean
        if (Build.VERSION.SDK_INT >= 16) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_FULLSCREEN;
        }

        if (Build.VERSION.SDK_INT >= 18) {
            newUiOptions ^= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        }

        getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
        //END_INCLUDE (set_ui_flags)
    }
    
answered by 17.04.2017 / 22:54
source