WebView+Fragment+ViewPager构建浏览器多标签页

来源:互联网 发布:fanuc机器人手动编程 编辑:程序博客网 时间:2024/05/17 22:54

本人第一次写csdn博客,如有错漏或有更好的实现方法欢迎提出!

以下只列出实现该功能的核心类,文末有完整代码的地址。

自定义ViewPager用于解决滑动冲突

public class MyViewPager extends ViewPager implements OnGestureListener{    private boolean isFullScreen=true;  //用于标识viewpager是否拦截事件,防止影响标签的左右滑动    private OnLayoutClickListener lc;    private GestureDetector gestureDetector;    private boolean canDel=true;    public MyViewPager(Context context) {        this(context,null);    }    public MyViewPager(Context context, AttributeSet attrs) {        super(context, attrs);            gestureDetector=new GestureDetector(context,this);        this.addOnPageChangeListener(new OnPageChangeListener() {            @Override            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {            }            @Override            public void onPageSelected(int position) {            }            @Override            public void onPageScrollStateChanged(int state) {                //防止viewpager在滚动中item仍可以上下滑动                if(state==SCROLL_STATE_IDLE){                    canDel=true;                }else{                    canDel=false;                }            }        });    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        if(!isFullScreen){            return true;        }        return false;    }    private FrameLayout frameLayout;    protected float point_x, point_y; //手指按下的位置    private int left, right, top, bottom;    private int measureWidth,measureHeight;    @Override    public boolean onTouchEvent(MotionEvent ev) {        if (ev.getAction() == MotionEvent.ACTION_DOWN) {            frameLayout= WebPage.frameLayouts.get(getCurrentItem());            measureWidth=frameLayout.getMeasuredWidth();            measureHeight=frameLayout.getMeasuredHeight();            point_x = ev.getRawX();            point_y = ev.getRawY();            left = frameLayout.getLeft();            right = frameLayout.getRight();            top = frameLayout.getTop();            bottom = frameLayout.getBottom();        }        if (ev.getAction() == MotionEvent.ACTION_MOVE){            float mov_x = ev.getRawX() - point_x;            float mov_y = ev.getRawY() - point_y;            if(Math.abs(mov_x) < Math.abs(mov_y)&&canDel){                frameLayout.measure(MeasureSpec.makeMeasureSpec(measureWidth,MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(measureHeight,MeasureSpec.AT_MOST));                frameLayout.layout(left, (int) mov_y, right, bottom + (int) mov_y);            }        }        if (ev.getAction() == MotionEvent.ACTION_UP){//手指释放后判断标签页是要删除还是复位            if(Math.abs(frameLayout.getTop())>frameLayout.getWidth()/2){                EventBus.getDefault().post(new MessageEvent(frameLayout.getTop()));            }else {                frameLayout.measure(MeasureSpec.makeMeasureSpec(measureWidth,MeasureSpec.AT_MOST),MeasureSpec.makeMeasureSpec(measureHeight,MeasureSpec.AT_MOST));                frameLayout.layout(left,0,right,bottom);            }                        }        gestureDetector.onTouchEvent(ev);        return super.onTouchEvent(ev);    }    public void setFullScreen(boolean fullScreen) {        isFullScreen = fullScreen;    }    public void setOnLayoutClickListener(OnLayoutClickListener lc){        this.lc=lc;    }    @Override    public boolean onDown(MotionEvent e) {        return true;    }    @Override    public void onShowPress(MotionEvent e) {    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        lc.onLayoutClick();       //手指点击屏幕不滑动时调用        return true;    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        return false;    }    @Override    public void onLongPress(MotionEvent e) {    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        if(Math.abs(velocityY)>7000){            EventBus.getDefault().post(new MessageEvent(frameLayout.getTop()));            return true;        }        if(Math.abs(frameLayout.getTop())>frameLayout.getWidth()/2){            EventBus.getDefault().post(new MessageEvent(frameLayout.getTop()));        }else {            frameLayout.layout(left,0,right,bottom);        }        return true;    }    public interface OnLayoutClickListener{        void onLayoutClick();    }}

注意FragmentPagerAdapter和FragmentStatePagerAdapter的区别,由于要保持webview的状态,使用FragmentPagerAdapter比较好,但在删除标签页后要手动删除fragment,否则会导致内存泄露。调用notifyDataSetChanged后系统会调用destroyItem,在方法内执行fragment缓存删除。

public class WebPageAdapter extends FragmentPagerAdapter {    private FragmentManager fm;    public static final int ADDWEBPAGE=0;    public static final int DELETEWEBPAGE=1;    private int notifyType=1;    public WebPageAdapter(Context context, FragmentManager fm) {        super(fm);        this.fm=fm;    }    @Override    public WebViewFragment getItem(int position) {        return WebPage.webpagelist.get(position);    }    @Override    public long getItemId(int position) {//默认是直接返回position,会导致删除时标签页顺序错乱,所以要返回hash码        return WebPage.webpagelist.get(position).hashCode();    }    @Override    public int getItemPosition(Object object) {//必须返回该值调用notifyDataSetChanged才有效        return POSITION_NONE;    }    @Override    public int getCount() {        return WebPage.webpagelist.size();    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        return super.instantiateItem(container,position);    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        if(notifyType==1&&position==WebPage.deleteItem){            fm.beginTransaction().remove((Fragment) object).commit();            WebPage.deleteItem=-1;            return;        }        super.destroyItem(container, position, object);    }    public void notifyDataSetChanged(int type) {        if(type==ADDWEBPAGE){            notifyType=0;        }else{            notifyType=1;        }        super.notifyDataSetChanged();    }}



public class WebPage {    public static List<WebViewFragment> webpagelist=new ArrayList<>(); //标签页集合    public static List<FrameLayout> frameLayouts=new ArrayList<>();//标签页的父视图集合,用于上下滑删除标签页动画对象    public static List<WebView> webViews=new ArrayList<>();       //webview对象集合    public static int page_interval=40;  //界面之间的间隔    public static int deleteItem=-1;  //当前的界面}


注:标签页的删除用到了依赖库EventBus。



完整代码看github(有更新),程序仍有待改进。

源码地址:https://github.com/Z-bm/Ming-Browser.git

原创粉丝点击