1

I am about to perform Zoom IN and OUT operations on a TextView which contains text. I am able to Zoom IN and OUT, but I need to make Zoom functions much Smoother(like Zooming a page in Chrome Browser). While performing Zoom-In and Zoom-Out operations (Using Pinch Zoom method), I am Zooming the Text content in a center aligned manner, I want to Zoom the content where I am Zooming in. I am attaching the code done by me, kindly suggest a solution for me.

Here is my activity file:

 public class ZoomTextView extends TextView {
     private static final String TAG = "ZoomTextView";
     private ScaleGestureDetector mScaleDetector;

     private float mScaleFactor = 1.f;
     private float defaultSize;

     private float zoomLimit = 3.0f;


     public ZoomTextView(Context context) {
         super(context);
         initialize();
     }

     public ZoomTextView(Context context, AttributeSet attrs) {
         super(context, attrs);
         initialize();
     }

     public ZoomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         initialize();
     }

     private void initialize() {
         defaultSize = getTextSize();
         mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());

     }

     /***
      * @param zoomLimit
      * Default value is 3, 3 means text can zoom 3 times the default size
      */

     public void setZoomLimit(float zoomLimit) {
         this.zoomLimit = zoomLimit;
     }

     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }

     @Override
     public boolean onTouchEvent(@NonNull MotionEvent ev) {
         super.onTouchEvent(ev);
         mScaleDetector.onTouchEvent(ev);
         return true;
     }

     /*Scale Gesture listener class,
     mScaleFactor is getting the scaling value
     and mScaleFactor is mapped between 1.0 and and zoomLimit
     that is 3.0 by default. You can also change it. 3.0 means text
     can zoom to 3 times the default value.*/

     private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
         @Override
         public boolean onScale(ScaleGestureDetector detector) {
             mScaleFactor *= detector.getScaleFactor();
             mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, zoomLimit));
             setTextSize(TypedValue.COMPLEX_UNIT_PX, defaultSize * mScaleFactor);
             Log.e(TAG, String.valueOf(mScaleFactor));
             return true;
         }
     } }

Here is my .xml file:

 <noman.zoomtextview.ZoomTextView
     android:layout_width="match_parent"
     android:layout_height="match_parent"

     android:layout_alignParentTop="true"
     android:layout_alignParentLeft="true"
     android:text="@string/sample_string"/> </RelativeLayout>

Thanks in advance.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Suresh S
  • 41
  • 10

3 Answers3

2

I think you should use magnifier, by this way

The magnifier can be programmatically used on an arbitrary view as follows:

View view = findViewById(R.id.view);
Magnifier magnifier = new Magnifier(view);
magnifier.show(view.getWidth() / 2, view.getHeight() / 2);

Here View can be replaced with TextView or Any specific view

Aniruddh Parihar
  • 3,072
  • 3
  • 21
  • 39
  • Actually your Idea is good but the Magnifier functions need API level 28, which is less consumed by customers now. Moreover my apk's Target level is 25 i.e MarshMallow. Can you Help me with another feasible solution – Suresh S Sep 05 '18 at 07:35
  • then you can increase the textSize of textView programmatically, this option will work in every API devices. – Aniruddh Parihar Sep 05 '18 at 08:18
  • And another way is use WebView to Show TextView content, because webView has Default zoom in zoom out property. – Aniruddh Parihar Sep 05 '18 at 08:20
0

If you don't mind adding another library, try the gesture view layout

more specifically, https://static.javadoc.io/com.alexvasilkov/gesture-views/2.5.2/com/alexvasilkov/gestures/views/GestureFrameLayout.html

basically you wrap your text view inside the GestureFrameLayout in the XML. it'll automatically detect zoom, pinch and pan based on your fingers' position and gestures. no extra coding required out of the box (unless if you want to implement non-default functionality like rotation, crop etc)

the usage example is here https://github.com/alexvasilkov/GestureViews/wiki/Usage

<com.alexvasilkov.gestures.views.GestureFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- GestureFrameLayout can contain only one child -->

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Layout content goes here -->

</FrameLayout>

Angel Koh
  • 12,479
  • 7
  • 64
  • 91
0

I have worked on Zoom In/Out for a View which can have multiple child(any kind of view and textview is included).

My Project

I use ScaleX and ScaleY api to zoom the parent view.

private fun applyScaleAndTranslationToChild() {
        child().scaleX = scaleFactor
        child().scaleY = scaleFactor
        child().pivotX = 0f  // default is to pivot at view center
        child().pivotY = 0f  // default is to pivot at view center
        child().translationX = translateX
        child().translationY = translateY
    }

above method is used to apply zoom in and out, and focus of zooming is also fixed.

I use ScaleGestureListener to get the scale (pinch gesture is captured by this)

inner class ScaleListner : ScaleGestureDetector.SimpleOnScaleGestureListener() {

        override fun onScale(scaleDetector: ScaleGestureDetector?): Boolean {
            val scaleFactor = scaleDetector!!.scaleFactor
            setScaleAndTranslation(scaleFactor, scaleDetector.focusX, scaleDetector.focusY)
            return true
        }

        override fun onScaleEnd(detector: ScaleGestureDetector?) {
            super.onScaleEnd(detector)
            setLayoutParamOfChild()
        }

        private fun setScaleAndTranslation(scaleFactor: Float, focusX: Float, focusY: Float) {
            if (lastScaleFactor == 0f || Math.signum(scaleFactor) == Math.signum(lastScaleFactor)) {
                val prevScale = this@ZoomView.scaleFactor
                this@ZoomView.scaleFactor *= scaleFactor
                this@ZoomView.scaleFactor = Math.max(MIN_ZOOM, Math.min(this@ZoomView.scaleFactor, MAX_ZOOM))
                lastScaleFactor = scaleFactor
                val adjustedScaleFactor = this@ZoomView.scaleFactor / prevScale
                // added logic to adjust translateX and translateY for pinch/zoom pivot point
                translateX += (translateX - focusX) * (adjustedScaleFactor - 1)
                translateY += (translateY - focusY) * (adjustedScaleFactor - 1)
            } else {
                lastScaleFactor = 0f
            }
            isSingleTapConfirmed = false
        }
    }

Refer to my Question all details are here.

Android: Zooming EditText Android Issue in translation And Getting Touch event of childView when Placed outside parentView

Anmol
  • 8,110
  • 9
  • 38
  • 63