5

I have a viewpager, where each page has to show a different WebView. This WebView should allow horizontall scrool, and I want to swipe to next page when the scroll finishes.

I've searched, and find some solutions, but nothing I did resolve this issue. I have a CustomViewPager and a CustomWebView for trying to handle scroll events.

This is my code:

Custom ViewPager

public class WebViewPager extends ViewPager {

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

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if (v instanceof ExtendedWebView) {
            return ((ExtendedWebView) v).canScrollHor(-dx);
        } else {
            return super.canScroll(v, checkV, dx, x, y);
        }
    }
}

Custom WebView

public class ExtendedWebView extends WebView {

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

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

    public boolean canScrollHor(int direction) {
        final int offset = computeHorizontalScrollOffset();
        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
        if (range == 0)
            return false;
        if (direction < 0) {
            return offset > 0;
        } else {
            return offset < range - 1;
        }
    }   
}

ScreenSlidePagerActivity

public class ScreenSlidePagerActivity extends FragmentActivity {

    class MyPageAdapter extends FragmentPagerAdapter {
        private List<Fragment> fragments;
        private List<String> titles;

        public MyPageAdapter(FragmentManager fm) {
            super(fm);
            this.fragments = new ArrayList<Fragment>();
            this.titles = new ArrayList<String>();
        }

        public void addItem(String url, String title) {
            Fragment myFragment = new WebViewFragment();
            Bundle args = new Bundle();
            args.putString("url", url);
            myFragment.setArguments(args);
            this.fragments.add(myFragment);
            this.titles.add(title);
        }

        @Override
        public Fragment getItem(int position) {
            return this.fragments.get(position);
        }

        public CharSequence getPageTitle(int position) {
            return this.titles.get(position);
        }

        @Override
        public int getCount() {
            return this.fragments.size();
        }
    }

    private MyPageAdapter pageAdapter = null;
    private WebViewPager pager = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pageAdapter = new MyPageAdapter(getSupportFragmentManager());
        pageAdapter.addItem("url1", "WebView 1");
        pageAdapter.addItem("url2", "WebView 2");
        pageAdapter.addItem("url3", "WebView 3");

        pager = (WebViewPager) findViewById(R.id.pager);

        pager.setOffscreenPageLimit(pageAdapter.getCount() - 1);
        pager.setAdapter(pageAdapter);
    }
}

Layout of the activity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="0dp"
    android:paddingLeft="0dp"
    android:paddingRight="0dp"
    android:paddingTop="0dp"
    tools:context=".MainActivity" >

    <com.example.viewpagerexample.WebViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="6dp"
        android:paddingTop="0dp" >

        <android.support.v4.view.PagerTabStrip
            android:id="@+id/pager_header"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:background="#fff"
            android:paddingBottom="0dp"
            android:paddingLeft="0dp"
            android:paddingRight="0dp"
            android:paddingTop="0dp"
            android:textColor="#000" />
    </com.example.viewpagerexample.WebViewPager>

</LinearLayout>

UPDATE The accepted answer only worked if I put this parameter in the CSS of my web page:

display: table;

Apparently, without this parameter the WebView is not able to calculate the width of its content.

androidevil
  • 8,770
  • 14
  • 40
  • 79

1 Answers1

5

Set following properties to your WebView

<your.package.name.MyWebView
  android:id="@+id/webview"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" 
 />

    mWebView.setInitialScale(120);
    mWebView.setScrollContainer(true);
    mWebView.bringToFront();
    mWebView.setScrollbarFadingEnabled(true);
    mWebView.setVerticalScrollBarEnabled(true);
    mWebView.setHorizontalScrollBarEnabled(true);
    mWebView.getSettings().setBuiltInZoomControls(true);
    mWebView.getSettings().setJavaScriptEnabled(false);
    mWebView.getSettings().setUseWideViewPort(true);
    mWebView.getSettings().setUserAgentString("Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3");

1. implement a custom ViewPager Instance like this:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

public class CustomViewPager extends ViewPager {

    private MagazineWebView_WithoutFlipWebView mCurrentPageWebView_; //custom webview

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {

        if (Constants.LOGGING) {
            Log.v(Constants.LOG_OEAMTC_APP, "CustomViewPager - onInterceptTouchEvent");
        }

        // if view zoomed out (view starts at 33.12... scale level) ... allow
        // zoom within webview, otherwise disallow (allow viewpager to change
        // view)
        if (mCurrentPageWebView_ != null && (mCurrentPageWebView_.getScale() * 100) > 34) {
            Log.v(Constants.LOG_OEAMTC_APP, "CustomViewPager - intrcepted: " + String.valueOf((mCurrentPageWebView_.getScale() * > 100)));
            this.requestDisallowInterceptTouchEvent(true);
        }
        else {
            if (mCurrentPageWebView_ != null) {
                Log.v(Constants.LOG_OEAMTC_APP,
                        "CustomViewPager - not intrcepted: " + String.valueOf(mCurrentPageWebView_.getScale() * 100));
            }
            this.requestDisallowInterceptTouchEvent(false);
        }

        return super.onInterceptTouchEvent(event);
    }

    public MagazineWebView_WithoutFlipWebView getCurrentPageWebView() {
        return mCurrentPageWebView_;
    }

    public void setCurrentPageWebView(MagazineWebView_WithoutFlipWebView currentPageWebView) {
        mCurrentPageWebView_ = currentPageWebView;
    }
}

2. in your main (ViewPager) Activity add the following lines to the view pager

mViewPager_ = new AwesomePagerAdapter();
        viewpapgerInLayout = (CustomViewPager) findViewById(R.id.awesomepager);
        viewpapgerInLayout.setAdapter(mViewPager_);
        viewpapgerInLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                  viewpapgerInLayout.setCurrentPageWebView(mLstPagesWebviews_.get(position));
            }

            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

3. finally, run it :=) if the zoom level is at initial zoom, changes pages is allowed, all the other time you can navigate your web view

Alternatively you can also extend your WebView but not both altogether

@Override
public boolean onInterceptTouchEvent(MotionEvent p_event)
{
    return true;
}

@Override
public boolean onTouchEvent(MotionEvent p_event)
{
    if (p_event.getAction() == MotionEvent.ACTION_MOVE && getParent() != null)
    {
        getParent().requestDisallowInterceptTouchEvent(true);
    }

    return super.onTouchEvent(p_event);
}
AZ_
  • 36,879
  • 28
  • 155
  • 201
  • First of all, have you tested this solution? I saw a solution here in SO that is equals yours, and I tried it, but it did not work. Really you just copied and pasted the solution of this question: http://stackoverflow.com/questions/8782637/scroll-webview-in-viewpager? ps: I don't want to scroll the webview depending on the the level of zomm. – androidevil Oct 28 '14 at 14:36
  • I am also having the same problem. It fixed it. You can write a javascript method (in your webpage, if you have access to it) and see if more scroll is available or not. if web-view scroll is not available then enable your viewPager. – AZ_ Oct 29 '14 at 02:43
  • 1
    Ok. Thank you anyway. I already had tried this solution before, and it did not work for me. It only worked when I put a parameter in the CSS of my WebView (display: table). Apparently, without this parameter the webview is not able to calculate the width of its content. – androidevil Nov 03 '14 at 12:38
  • Please consider updating your question with your solution like including CSS or any more information that will help community. – AZ_ Nov 04 '14 at 02:31
  • 1
    this solution is not working...n please dont create duplicate answers on forum. – krunal patel Jul 16 '15 at 11:18
  • @krunalpatel there is an option to mark as duplicate please use this option. – AZ_ Jul 17 '15 at 06:42