Java tutorial
/* * Copyright (C) 2015 Egor Andreevici * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.egorand.scrollableimageview; import android.content.Context; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.widget.ImageView; import android.widget.OverScroller; /** * An extension to the standard Android {@link ImageView}, which makes it * respond to Scroll and Fling events. Uses a {@link GestureDetectorCompat} and * a {@link OverScroller} to provide scrolling functionality. * * @author EgorAnd */ public class ScrollableImageView extends ImageView { private GestureDetectorCompat gestureDetector; private OverScroller overScroller; private final int screenW; private final int screenH; private int positionX = 0; private int positionY = 0; public ScrollableImageView(Context context) { super(context); // We will need screen dimensions to make sure we don't overscroll the // image DisplayMetrics dm = getResources().getDisplayMetrics(); screenW = dm.widthPixels; screenH = dm.heightPixels; gestureDetector = new GestureDetectorCompat(context, gestureListener); overScroller = new OverScroller(context); } public ScrollableImageView(Context context, AttributeSet attrs) { super(context, attrs); // We will need screen dimensions to make sure we don't overscroll the // image DisplayMetrics dm = getResources().getDisplayMetrics(); screenW = dm.widthPixels; screenH = dm.heightPixels; gestureDetector = new GestureDetectorCompat(context, gestureListener); overScroller = new OverScroller(context); } @Override public boolean onTouchEvent(MotionEvent event) { gestureDetector.onTouchEvent(event); return true; } @Override public void computeScroll() { super.computeScroll(); // computeScrollOffset() returns true only when the scrolling isn't // already finished if (overScroller.computeScrollOffset()) { positionX = overScroller.getCurrX(); positionY = overScroller.getCurrY(); scrollTo(positionX, positionY); } else { // when scrolling is over, we will want to "spring back" if the // image is overscrolled overScroller.springBack(positionX, positionY, 0, getMaxHorizontal(), 0, getMaxVertical()); } } private int getMaxHorizontal() { return (Math.abs(getDrawable().getBounds().width() - screenW)); } private int getMaxVertical() { return (Math.abs(getDrawable().getBounds().height() - screenH)); } private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { overScroller.forceFinished(true); ViewCompat.postInvalidateOnAnimation(ScrollableImageView.this); return true; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { overScroller.forceFinished(true); overScroller.fling(positionX, positionY, (int) -velocityX, (int) -velocityY, 0, getMaxHorizontal(), 0, getMaxVertical()); ViewCompat.postInvalidateOnAnimation(ScrollableImageView.this); return true; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { overScroller.forceFinished(true); // normalize scrolling distances to not overscroll the image int dx = (int) distanceX; int dy = (int) distanceY; int newPositionX = positionX + dx; int newPositionY = positionY + dy; if (newPositionX < 0) { dx -= newPositionX; } else if (newPositionX > getMaxHorizontal()) { dx -= (newPositionX - getMaxHorizontal()); } if (newPositionY < 0) { dy -= newPositionY; } else if (newPositionY > getMaxVertical()) { dy -= (newPositionY - getMaxVertical()); } overScroller.startScroll(positionX, positionY, dx, dy, 0); ViewCompat.postInvalidateOnAnimation(ScrollableImageView.this); return true; } }; public void translate(String direction) { float distanceX = 0; float distanceY = 0; if (direction.equals("LEFT")) { distanceX = -10; } else if (direction.equals("RIGHT")) { distanceX = 10; } else if (direction.equals("UP")) { distanceY = -10; } else if (direction.equals("DOWN")) { distanceY = 10; } overScroller.forceFinished(true); // normalize scrolling distances to not overscroll the image int dx = (int) distanceX; int dy = (int) distanceY; int newPositionX = positionX + dx; int newPositionY = positionY + dy; if (newPositionX < 0) { dx -= newPositionX; } else if (newPositionX > getMaxHorizontal()) { dx -= (newPositionX - getMaxHorizontal()); } if (newPositionY < 0) { dy -= newPositionY; } else if (newPositionY > getMaxVertical()) { dy -= (newPositionY - getMaxVertical()); } overScroller.startScroll(positionX, positionY, dx, dy, 0); ViewCompat.postInvalidateOnAnimation(ScrollableImageView.this); } }