2

I would like to make a TextView that can change the size of it's text based on pinch zooming. The TextView is inside a ScrollView. I've got the TextView to zoom when pinching BUT only when you move your fingers almost perfectly horizontally. If there is a vertical component to the pinch-zoom it defaults to scrolling instead of zooming

Is there a way to disable the scrolling of the ScrollView when there is more than 1 pointer on it then re-enable scrolling when the pointer count returns to 1 or 0? Is the best way to create a CustomScrollView widget or is there an easier way?

Uwais A
  • 737
  • 6
  • 23
  • Do you actually zooming or just changing the text size? Also, since TextView has already scrolling capabilities putting it into a ScrollView might cause issues.Just use TextView with maxLines attribute. – Onur May 24 '14 at 20:28
  • The 'pinch-zooming' that I am using doesn't actually zoom, it just changes the text size because I'd like to keep the width of the TextView constant and just extend the height. The ScrollView doesn't cause any issues for me, but even if I changed it to the scrolling TextView the question stays the same. – Uwais A May 24 '14 at 20:39

4 Answers4

5

I think it is simpler to use:

   textView.setOnTouchListener(new View.OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if(event.getPointerCount() == 1) {
                Log.d("Scroll","1-pointer touch");
                v.getParent().requestDisallowInterceptTouchEvent(false);

            }
            if(event.getPointerCount() == 2){
                Log.d("Zoom","2-pointer touch");
                v.getParent().requestDisallowInterceptTouchEvent(true);

            }
            return false;
        }
    });
Richter
  • 164
  • 2
  • 6
4

Inspired by this answer https://stackoverflow.com/a/14577399/2014236

scaleGD = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
mTextView.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getPointerCount() == 1){
            //stuff for 1 pointer
        }else{ //when 2 pointers are present
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // Disallow ScrollView to intercept touch events.
                v.getParent().requestDisallowInterceptTouchEvent(true);
                scaleGD.onTouchEvent(event);
                break;

            case MotionEvent.ACTION_MOVE:
                // Disallow ScrollView to intercept touch events.
                v.getParent().requestDisallowInterceptTouchEvent(true);
                scaleGD.onTouchEvent(event);
                break;

            case MotionEvent.ACTION_UP:
                // Allow ScrollView to intercept touch events.
                v.getParent().requestDisallowInterceptTouchEvent(false);
                break;
            }
        }
        return true;
    }
});

EDIT:

//later in the code
public class simpleOnScaleGestureListener extends SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        float size = codedText.getTextSize();
        float factor = detector.getScaleFactor();
        int increase = 0;
        if(factor > 1.0f)
            increase = 2;
        else if(factor < 1.0f)
            increase = -2;

        size += increase;

        codedText.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
        plainText.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);            
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //remembering the favourable text size
        Editor edit = sp.edit();
        edit.putFloat("TXTSIZE", size);
        edit.commit();
        return true;
    }
}

By no means perfect but does a good enough job for me - feel free to make improvements.

Community
  • 1
  • 1
Uwais A
  • 737
  • 6
  • 23
  • can you provide the code for changing the fonts cause i can't figure it out – Libathos Jul 17 '14 at 13:32
  • Not perfect but good enough for my app where this experience is only likely to happen once or twice in the lifetime of the app's use. Does the edit solve your issue? – Uwais A Jul 17 '14 at 18:07
  • It's a SharedPreferences object. This stores the size then elsewhere in the code I set the size to this value next time so the user doesn't have to zoom every time – Uwais A Jul 18 '14 at 11:02
  • When i place to fingers without move it, the text size changes. Could you fix it? – Tuss Jan 13 '16 at 03:46
  • it is a very "laggy" solution to be honest, do you have any way of improving it? @Uwais A – Lidor Eliyahu Shelef Dec 13 '20 at 11:16
0

Here is a nice a sample code from android-dev blog that shows how to implement finger pinch.

Android touch example

You cannot disable scroll feature of scroll bar unless you dont override the onTouchEvent method to return false on your condition. Here are few threads that may help you on how to disable scrolling in scroll view.

How to disable scrolling in ScrollView when the viewSwitcher is enabled?

How to disable ScrollView scrolling?

Disable ScrollView Programmatically?

Thank you :)

Community
  • 1
  • 1
Saqib Vohra
  • 366
  • 7
  • 17
0

I'm using this solution. Crédits for Zoom Algorithm in this vídeo

Use a TextView without ScrollView, just use android:scrollbars="vertical"

        <TextView
        android:id="@+id/activity_content_text_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_weight="1"
        android:gravity="fill"
        android:textSize="8pt"
        android:scrollbars="vertical"
        />

Java:

public class MainActivity extends Activity implements View.OnTouchListener {

   private TextView textContent = null;
   private final static float move = 200;
   private float ratio = 1.0f;
   private int baseDist;
   private float baseRatio;

   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.teste_layout);
       textContent = findViewById(R.id.activity_content_text_content);
       textContent.setText("Lorem ipsum dolor sit amet......");

       textContent.setMovementMethod(new ScrollingMovementMethod());
       textContent.setOnTouchListener(this);
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return onTouchEvent(event);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getPointerCount() == 2){

            int action = event.getAction();
            int mainAction = action&MotionEvent.ACTION_MASK;

            if(mainAction == MotionEvent .ACTION_POINTER_DOWN){
                    baseDist = getDisTance(event);
                    baseRatio = ratio;
                } else {
                    float scale = (getDisTance(event)-baseDist)/move;
                    float factor = (float)Math.pow(2, scale);
                ratio = Math.min(1024.0f, Math.max(0.1f, baseRatio*factor));
                textContent.setTextSize(ratio+15);
            }
        } else {
            return false;
        }
        return true;
    }

    private int getDisTance(MotionEvent event) {
        int dx = (int) (event.getX(0)-event.getX(1));
        int dy = (int) (event.getY(0)-event.getY(1));
        return (int) (Math.sqrt(dx*dx+dy*dy));
    }
}

Developer at Frevo Studios