ArrayIndexOutOfBoundsException in PhotoView + ViewPager

3.5k views Asked by At

I'm using the PhotoView library, however when using it with viewpager I get an error when zooming.

08-22 17:14:50.096: E/AndroidRuntime(8740): FATAL EXCEPTION: main
08-22 17:14:50.096: E/AndroidRuntime(8740): java.lang.IllegalArgumentException: pointerIndex out of range
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.MotionEvent.nativeGetAxisValue(Native Method)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.MotionEvent.getX(MotionEvent.java:2148)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.support.v4.view.MotionEventCompatEclair.getX(MotionEventCompatEclair.java:32)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.support.v4.view.MotionEventCompat$EclairMotionEventVersionImpl.getX(MotionEventCompat.java:91)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.support.v4.view.MotionEventCompat.getX(MotionEventCompat.java:219)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1834)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1909)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2270)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2010)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2270)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2010)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2270)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2010)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2270)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2010)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2182)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1512)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.app.Activity.dispatchTouchEvent(Activity.java:2466)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2130)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.View.dispatchPointerEvent(View.java:7641)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3682)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3613)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4804)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4783)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4875)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:174)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4854)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4894)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.Choreographer.doCallbacks(Choreographer.java:562)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.Choreographer.doFrame(Choreographer.java:530)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.os.Handler.handleCallback(Handler.java:725)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.os.Handler.dispatchMessage(Handler.java:92)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.os.Looper.loop(Looper.java:137)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at android.app.ActivityThread.main(ActivityThread.java:5328)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at java.lang.reflect.Method.invokeNative(Native Method)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at java.lang.reflect.Method.invoke(Method.java:511)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
08-22 17:14:50.096: E/AndroidRuntime(8740):     at dalvik.system.NativeStart.main(Native Method)
08-22 17:15:18.416: D/dalvikvm(8872): GC_FOR_ALLOC freed 94K, 14% free 17782K/20656K, paused 13ms, total 13ms

Though, the zooming works great but when the image become far, then the error occurs and my activity crash.. Here's my codes in viewapager:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        pv = new PhotoView(getActivity());
        pv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        imageLoader.DisplayImage(mContent, pv);
        LinearLayout layout = new LinearLayout(getActivity());
        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        layout.setGravity(Gravity.CENTER);
        layout.addView(pv);

        return layout;
    }

I googled the issue, but couldn't find any proper solution! any suggestion?? Thanks guys

My whole codes:

public class viewpager extends SherlockFragmentActivity {

AllPhonesDatabase apd;
Bundle gotBasket;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.simple_circles);

    apd = new AllPhonesDatabase(this.getApplicationContext()).open();
    gotBasket = viewpager.this.getIntent().getExtras();
    final String imageurl1 = gotBasket.getString("Imageurl1");
    final String imageurl2 = gotBasket.getString("Imageurl2");
    final String imageurl3 = gotBasket.getString("Imageurl3");

    TestFragmentAdapter mAdapter = new TestFragmentAdapter(
            this.getSupportFragmentManager(), imageurl1, imageurl2,
            imageurl3);
    ViewPager mPager = (ViewPager) findViewById(R.id.pager);
    mPager.setAdapter(mAdapter);
    CirclePageIndicator mIndicator = (CirclePageIndicator) findViewById(R.id.indicator);
    mIndicator.setViewPager(mPager);

}

}

class TestFragmentAdapter extends FragmentPagerAdapter {
    protected static String[] CONTENT;

    private int mCount;

    public TestFragmentAdapter(FragmentManager fm, String imageurl1,
            String imageurl2, String imageurl3) {
        super(fm);
        CONTENT = new String[] { imageurl1, imageurl2, imageurl3 };
        mCount = CONTENT.length;
    }

    @Override
    public Fragment getItem(int position) {
        return TestFragment.newInstance(CONTENT[position % CONTENT.length]);
    }

    @Override
    public int getCount() {
        return mCount;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return TestFragmentAdapter.CONTENT[position % CONTENT.length];
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    }


public final class TestFragment extends Fragment {
    private static final String KEY_CONTENT = "TestFragment:Content";
    public ImageLoader2 imageLoader;
    PhotoView pv;

    public static TestFragment newInstance(String content) {
        TestFragment fragment = new TestFragment();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 1; i++) {
            builder.append(content).append(" ");
        }
        builder.deleteCharAt(builder.length() - 1);
        fragment.mContent = builder.toString();
        return fragment;
    }

    private String mContent = "???";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageLoader = new com.androidarabia.lazylist.ImageLoader2(
                this.getActivity());
        if ((savedInstanceState != null)
                && savedInstanceState.containsKey(KEY_CONTENT)) {
            mContent = savedInstanceState.getString(KEY_CONTENT);
        }
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        pv = new PhotoView(getActivity());
        pv.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        imageLoader.DisplayImage(mContent, pv);
        LinearLayout layout = new LinearLayout(getActivity());
        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT));
        layout.setGravity(Gravity.CENTER);
        layout.addView(pv);

        return layout;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_CONTENT, mContent);
    }
4

There are 4 answers

5
tim.paetz On BEST ANSWER

It seems to be a bug some where along the lines. I'm not sure if it is on the PhotoViewer side or on androids side. I worked around this issue by using this code in my own custom view pager:

public class HackyViewPager extends ViewPager {


public HackyViewPager(Context context)
{
    super(context);
}

public HackyViewPager(Context context, AttributeSet attrs)
{
    super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    try
    {
            return super.onInterceptTouchEvent(ev);
    }
    catch (IllegalArgumentException e)
    {
    }
    catch (ArrayIndexOutOfBoundsException e)
    {

    }
    return false;
}
}

I've had no issues using this code and zooming in and zooming out seems to work fine. Create this class in your source code and then you can reference it in your xml files like this:

<my.default.package.HackyViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />
1
HT03 On

May be you should check if this is similar to a previous question here. java.lang.IllegalArgumentException: pointerIndex out of range Exception - dispatchTouchEvent

0
Ashish Kumar On

Obviously i agree to the hacky view pager thing, but i guess for the flawless implementation, one must use the photoViewAttacher.update(), after each image resource change, like in success ,failure listeners of the corresponding image loading library used

2
Vladimir Salguero On
  1. Create a new class HackyViewPager and paste this code

     public class HackyViewPager extends ViewPager {
    
    
     public HackyViewPager(Context context) {
         super(context);
     }
    
     public HackyViewPager(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
    
    
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         try {
                 return super.onInterceptTouchEvent(ev);
             } catch (IllegalArgumentException e) {
             } catch (ArrayIndexOutOfBoundsException e) {
    
             }
             return false;
         }
     }
    
  2. An you xml layout change the class of the viewPager component

     <android.support.v4.view.ViewPager
             android:layout_width="match_parent"
             android:elevation="0dp"
             android:id="@+id/viewPager"
             android:layout_height="match_parent">
     </android.support.v4.view.ViewPager>
    

    To

     <com.yourpackage.HackyViewPager
             android:layout_width="match_parent"
             android:elevation="0dp"
             android:id="@+id/viewPager"
             android:layout_height="match_parent">
     </com.yourpackage.HackyViewPager>
    
  3. Declare your viewPager variable with the class HackyViewPager

     HackyViewPager viewPager;
    

    Inside onCreate method

     viewPager = (HackyViewPager) findViewById(R.id.viewPager);