自定义ScrollView,实现导航条悬浮置顶

Android ScrollView向上滑动控件顶部悬浮效果实现
* 导航栏实现悬浮置顶效果(顶部图片隐藏,下面的单选框导航悬浮)
【上滑停靠顶端的悬浮框】里的实现方法是使用两个控件,滑动时,监听ScrollView的滚动Y值,
* 从而通过对两个控件的显示隐藏来实现控件的顶部悬浮。但是实际应用场景中,
* 有可能需要悬浮的控件里面的内容是比较多的,如果通过显示隐藏的方式来实现的话,
* 操作控件里的内容时,需要重复定义两套变量,对控件里的内容进行修改时也是要操作再次,非常麻烦。
本文的方法是通过addViewremoveView来实现的

	当外面嵌套一层ScrollView后,就能做上下或左右滑动,但能滑动多少系统不知道,
* 	这时就需要你给计算出一个滑动区域给ScrollView

知识点:

1、当ScrollView垂直滚动视图中嵌套ListView时,ListView必须重写onMeasure方法,返回高度和大小,否则,只会显示一行布局!!!

2、滑动事件会有冲突:重写onInterceptTouchEvent方法(或者其他事件的方法),根据情况获得事件!

首先继承ScrollView类:

public class HoveringScrollview extends ScrollView {
    private OnScrollListener onScrollListener;
    /**
     * 主要是用在用户手指离开本view,本view还在继续滑动,我们用来保存Y的距离,然后做比较
     */
    private int lastScrollY;

    public HoveringScrollview(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    /**
     * 设置滚动接口
     *
     * @param onScrollListener
     */
    public void setOnScrollListener(OnScrollListener onScrollListener) {
        this.onScrollListener = onScrollListener;
    }

    /**
     * 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中
     */
    private Handler handler = new Handler() {

        public void handleMessage(android.os.Message msg) {
            int scrollY = HoveringScrollview.this.getScrollY();

            // 此时的距离和记录下的距离不相等,在隔6毫秒给handler发送消息?
            if (lastScrollY != scrollY) {
                lastScrollY = scrollY;
                handler.sendMessageDelayed(handler.obtainMessage(), 6);
            }
            if (onScrollListener != null) {
                onScrollListener.onScroll(scrollY);
            }

        };

    };

    /**
     * 重写onTouchEvent, 当用户的手在HoveringScrollview上面的时候,
     * 直接将HoveringScrollview滑动的Y方向距离回调给onScroll方法中,当用户抬起手的时候,
     * HoveringScrollview可能还在滑动,所以当用户抬起手我们隔6毫秒给handler发送消息,在handler处理
     * HoveringScrollview滑动的距离
     */
    public boolean onTouchEvent(MotionEvent ev) {
        if (onScrollListener != null) {
            onScrollListener.onScroll(lastScrollY = this.getScrollY());
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP://用户把手拿开
                //发送信息回去
                handler.sendMessageDelayed(handler.obtainMessage(), 20);
                break;
        }
        return super.onTouchEvent(ev);
    };

    /**
     * 滚动的回调接口
     */
    public interface OnScrollListener {
        /**
         * 回调方法, 返回本view滑动的Y(上下)方向距离
         */
        public void onScroll(int scrollY);
    }

}

在Activity(Fragment)中:

重要方法:

    //获得组件的大小(Fragment中)
        ViewTreeObserver vto=rlayout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                searchLayoutTop=rlayout.getHeight();
            }
        });

 @Override//当hasFocus == true,表示加载完成    Activity中才有该方法
    public void onWindowFocusChanged(boolean hasFocus) {
        // TODO Auto-generated method stub
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            searchLayoutTop = rlayout.getBottom();// 获取searchLayout的顶部位置
        }
    }

Fragment中的JAVA代码:

public class Item_Fragment extends Fragment implements View.OnClickListener, HoveringScrollview.OnScrollListener {
    private HoveringScrollview hoveringScrollview;
    private int searchLayoutTop;

    ViewTop viewtop;
    LinearLayout hoveringLayout;
    LinearLayout search01, search02;
    RelativeLayout rlayout;
    RadioGroup radioGroup;
    FrameLayout layout;

    private ItemZI_Fragment1 fragment1;
    private ItemZI_Fragment2 fragment2;
    private ItemZI_Fragment3 fragment3,fragment4;

    private Bundle bundle;
    private Fragment currentFragment;//记录当前显示的碎片对象

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.item_fragment, container, false);
        initView(view);
        return view;
    }

    private void initView(View view) {
        view.findViewById(R.id.item_msg).setOnClickListener(this);
        view.findViewById(R.id.item_camera).setOnClickListener(this);

        //悬浮条线性布局(固定大小的布局)[首先嵌套在2号布局里面]
        hoveringLayout = (LinearLayout) view.findViewById(R.id.hoveringLayout);

        hoveringScrollview = (HoveringScrollview) view.findViewById(R.id.hoveringScrollview);//滚动视图
        search01 = (LinearLayout) view.findViewById(R.id.search01);//最下面的3号布局

        search02 = (LinearLayout) view.findViewById(R.id.search02);//2号布局

        rlayout = (RelativeLayout) view.findViewById(R.id.rlayout);//1号布局(顶部的内容)

        layout= (FrameLayout) view.findViewById(R.id.layout);

        radioGroup= (RadioGroup) view.findViewById(R.id.item_list_group);

        viewtop= (ViewTop) view.findViewById(R.id.viewtop);

        viewtop.setOnLienter(new ViewTop.OnListeren() {
            @Override
            public String[] getURL() {
                return URLClass.ItemTops;
            }
        });

        viewtop.setData(true);

        hoveringScrollview.setOnScrollListener(this);// set Listener  设置监听

        for (int i = 0; i <radioGroup.getChildCount() ; i++) {
            //遍历单选组里面的控件,设置点击事件
            ((RadioButton)radioGroup.getChildAt(i)).setOnClickListener(this);
        }

        //获取碎片管理器对象, //开启事物,获得操作碎片的对象
        FragmentTransaction transaction =getActivity().getSupportFragmentManager().beginTransaction();

        fragment1 = new ItemZI_Fragment1();
        bundle = new Bundle();
        bundle.putString("url",URLClass.ItemURL1);
        fragment1.setArguments(bundle);

        currentFragment = fragment1;//记录当前的碎片
        transaction.add(R.id.layout, fragment1);//添加帧布局和碎片对象
        transaction.commit();//提交事物

        //获得组件的大小(Fragment中)
        ViewTreeObserver vto=rlayout.getViewTreeObserver();
        vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                searchLayoutTop=rlayout.getHeight();
            }
        });

    }

  /*
    @Override//当hasFocus == true,表示加载完成    Activity中才有该方法
    public void onWindowFocusChanged(boolean hasFocus) {
        // TODO Auto-generated method stub
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            searchLayoutTop = rlayout.getBottom();// 获取searchLayout的顶部位置
        }
    }
*/

    @Override//实现的滚动方法
    public void onScroll(int scrollY) {
        // TODO Auto-generated method stub
        if (scrollY >= searchLayoutTop) {
            if (hoveringLayout.getParent() != search01) {
                search02.removeView(hoveringLayout);  //2号布局删除  悬浮体布局
                search01.addView(hoveringLayout);   //3号底层布局添加  悬浮体布局
            }
        } else {
            if (hoveringLayout.getParent() != search02) {
                search01.removeView(hoveringLayout);   //3号底层布局删除   悬浮体布局
                search02.addView(hoveringLayout);    //2号布局添加   悬浮体布局
            }
        }
    }

    private int counnt;
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.item_list_b1:
                counnt=0;
                showFragment(1);
                break;
            case R.id.item_list_b2:
                counnt=1;
                showFragment(2);
                break;
            case R.id.item_list_b3:
                counnt=2;
                showFragment(3);
                break;
            case R.id.item_list_b4:
                counnt=3;
                showFragment(4);
                break;
        }

        for (int i = 0; i <radioGroup.getChildCount() ; i++) {

            RadioButton button= (RadioButton) radioGroup.getChildAt(i);
            if(i==counnt){
                button.setTextColor(getResources().getColor(R.color.main_text_yes));
                continue;
            }
            button.setTextColor(getResources().getColor(R.color.main_text_no));
        }
    }

    //显示碎片对象,隐藏当前的碎片对象
    private void showFragment(int index) {
        //碎片操作对象,不能定义全局的,负责秒报错
        FragmentTransaction transaction =getActivity().getSupportFragmentManager().beginTransaction();

        if (index == 1) {//热门碎片
            if (fragment1 == null) {
                fragment1 = new ItemZI_Fragment1();
                bundle = new Bundle();
                bundle.putString("url",URLClass.ItemURL1);
                fragment1.setArguments(bundle);
            }
            if (fragment1.isAdded()) {//如果碎片对象存在
                transaction.show(fragment1);//显示该碎片
                transaction.hide(currentFragment);//隐藏当前碎片(前一个)
            } else {//如果碎片对象不存在
                transaction.add(R.id.layout, fragment1);//添加碎片
                transaction.hide(currentFragment);//隐藏当前的碎片
            }
            transaction.commit();//提交事件
            currentFragment = fragment1;//记录当前显示的碎片

        } else if (index == 2) {//关注碎片
            if (fragment2 == null) {
                fragment2 = new ItemZI_Fragment2();
                bundle = new Bundle();
                bundle.putString("url",URLClass.ItemURL2);
                fragment2.setArguments(bundle);
            }
            if (fragment2.isAdded()) {//如果碎片对象存在
                transaction.show(fragment2);//显示该碎片
                transaction.hide(currentFragment);//隐藏当前碎片(前一个)
            } else {//如果碎片对象不存在
                transaction.add(R.id.layout, fragment2);//添加碎片
                transaction.hide(currentFragment);//隐藏当前的碎片
            }
            transaction.commit();//提交事件
            currentFragment = fragment2;//记录当前显示的碎片

        } else if (index == 3) {//红人碎片
            if (fragment3 == null) {
                fragment3 = new ItemZI_Fragment3();
                bundle = new Bundle();
                bundle.putString("url",URLClass.ItemURL3);
                fragment3.setArguments(bundle);
            }
            if (fragment3.isAdded()) {//如果碎片对象存在
                transaction.show(fragment3);//显示该碎片
                transaction.hide(currentFragment);//隐藏当前碎片(前一个)
            } else {//如果碎片对象不存在
                transaction.add(R.id.layout, fragment3);//添加碎片
                transaction.hide(currentFragment);//隐藏当前的碎片
            }
            transaction.commit();//提交事件
            currentFragment = fragment3;//记录当前显示的碎片

        } else if (index == 4) {//线下店碎片
            if (fragment4 == null) {
                fragment4 = new ItemZI_Fragment3();
                bundle = new Bundle();
                bundle.putString("url",URLClass.ItemURL4);
                fragment4.setArguments(bundle);
            }
            if (fragment4.isAdded()) {//如果碎片对象存在
                transaction.show(fragment4);//显示该碎片
                transaction.hide(currentFragment);//隐藏当前碎片(前一个)
            } else {//如果碎片对象不存在
                transaction.add(R.id.layout, fragment4);//添加碎片
                transaction.hide(currentFragment);//隐藏当前的碎片
            }
            transaction.commit();//提交事件
            currentFragment = fragment4;//记录当前显示的碎片
        }

    }
}

XML布局:  顶部布局必须为相对布局,否则不会悬浮组件,会覆盖

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <!-- 社区的碎片的布局,相对布局才有效果-->
    <android.support.v7.widget.Toolbar
        android:id="@+id/item_toolbar"
        android:layout_width="match_parent"
        android:layout_height="50dp">
        <RelativeLayout
            android:layout_marginTop="8dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:layout_width="100dp"
                android:gravity="center"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:textSize="20sp"
                android:textColor="#181515"
                android:text="社区"
                />

            <ImageView
                android:id="@+id/item_msg"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:background="@mipmap/button_head_massage"/>

            <ImageView
                android:id="@+id/item_camera"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="20dp"
                android:layout_toLeftOf="@id/item_msg"
                android:layout_centerVertical="true"
                android:background="@mipmap/button_head_camera"/>

        </RelativeLayout>

    </android.support.v7.widget.Toolbar>

    <com.android.starapp.view.HoveringScrollview
        android:id="@+id/hoveringScrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <RelativeLayout
                android:id="@+id/rlayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal">

                <com.android.starapp.view.ViewTop
                    android:id="@+id/viewtop"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    />
            </RelativeLayout>

            <!-- 这个悬浮条必须是固定高度 -->
            <LinearLayout
                android:id="@+id/search02"
                android:layout_width="match_parent"
                android:layout_height="70dp">
                <LinearLayout
                    android:id="@+id/hoveringLayout"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:background="#fff"
                    >
                    <RadioGroup
                        android:id="@+id/item_list_group"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:orientation="horizontal"
                        android:weightSum="4">

                        <RadioButton
                            android:id="@+id/item_list_b1"
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="1"
                            android:button="@null"
                            android:checked="true"
                            android:drawableBottom="@drawable/match_toolbar_main"
                            android:gravity="center"
                            android:text="热门"
                            android:textColor="@color/main_text_yes" />

                        <RadioButton
                            android:id="@+id/item_list_b2"
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="1"
                            android:button="@null"
                            android:drawableBottom="@drawable/match_toolbar_main"
                            android:gravity="center"
                            android:text="关注"
                            android:textColor="@color/main_text_no" />

                        <RadioButton
                            android:id="@+id/item_list_b3"
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="1"
                            android:button="@null"
                            android:drawableBottom="@drawable/match_toolbar_main"
                            android:gravity="center"
                            android:text="红人"
                            android:textColor="@color/main_text_no" />

                        <RadioButton
                            android:id="@+id/item_list_b4"
                            android:layout_width="0dp"
                            android:layout_height="match_parent"
                            android:layout_weight="1"
                            android:button="@null"
                            android:drawableBottom="@drawable/match_toolbar_main"
                            android:gravity="center"
                            android:text="线下店"
                            android:textColor="@color/main_text_no" />

                    </RadioGroup>
                </LinearLayout>
            </LinearLayout>

            <FrameLayout
                android:id="@+id/layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                />
        </LinearLayout>
    </com.android.starapp.view.HoveringScrollview>

    <LinearLayout
        android:id="@+id/search01"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:orientation="vertical"></LinearLayout>

</RelativeLayout>
时间: 2024-11-08 03:53:30

自定义ScrollView,实现导航条悬浮置顶的相关文章

CSS自定义带动画导航条

图形: css代码: /* ================================================================ This copyright notice must be kept untouched in the stylesheet at all times. Copyright (c) 2005-2010 Stu Nicholls. All rights reserved. This stylesheet and the associated

001-导航条悬浮顶部

<!DOCTYPE> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <script src="http://www.w3school.com.cn/jquery/jquery-1.11.1.min.js"></script> <title>导航条

导航栏置顶固定悬浮

<!doctype html><html><head><meta charset="utf-8"><title>网友分享jQuery导航菜单悬浮置顶特效</title><style type="text/css"> *{ margin:0; padding:0;} body{ background:#eee; text-shadow:0px 1px 0px rgba(255,255,

在UWP中页面滑动导航栏置顶

最近在研究掌上英雄联盟,主要是用来给自己看新闻,顺便copy个界面改一下段位装装逼,可是在我copy的时候发现这个东西 当你滑动到一定距离的时候导航栏会置顶不动,这个特性在微博和淘宝都有,我看了@ms-uap的文章,淘宝的实现方式是改变顶部显示栏的大小,我本来准备按照他那个思路去做的,但发现效果不理想,在滑动的时候,底部的界面也跟着在滑动,这样使得很不友好,所以我准备自己实现一个 先上个最终效果图吧,图比较大,请耐心等待 思路大概是这样的 将这个界面分为两行 <Grid.RowDefinitio

网站的导航条下的指示器

eg:一般情况下,网站上的导航条会吸顶或者不做处理的,在处理吸顶情况:指示器的颜色会有不同的需求,在默认进入页面首页时,导航条的指示器颜色时黑色(看公司需求确定),鼠标在悬停到某一个产品会展示下方信息,一般的写法用对应的hover事件处理时没有问题的.在需要吸顶后在改变鼠标悬停的效果并且当前的指示器需要改变颜色(和之前的颜色不同)为白色.我们一般遇到会先到时在监听滚动时,去处理对应的事件,是没有问题的.但是呢,在遇到是要鼠标悬停时再去改变事件的时候,我们就不应再用hover  事件去处理,我们要

Android自定义ScrollView实现一键置顶功能

效果图如下: (ps:动态图有太大了,上传不了,就给大家口述一下要实现的功能吧) 要实现的功能:当ScrollView向上滑动超过一定距离后,就渐变的出现一个置顶的按钮,当滑动距离小于我们指定的距离时,按钮又消失. 实现原理:就是监听View的onScrollChanged()方法(回调方法),获取到ScrolView滑动的距离,如果大于我们的距离,则出现置顶按钮,否则,直接隐藏,且当按钮出现点击事件,让整个ScrollView滑动到(0,0)位置即可,不废话,直接上代码 自定义的ScrollV

低版本系统兼容的ActionBar(三)自定义Item视图+进度条的实现+下拉导航+透明ActionBar

       一.自定义MenuItem的视图 custom_view.xml (就是一个单选按钮) <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android

[知了堂学习笔记]_css3特效第二篇--行走的线条&amp;&amp;置顶导航栏

一.行走的线条. 效果图(加载可能会慢一点儿,请稍等...): html代码: 1 <div class="movingLines"> 2 <img src="images/ser2.jpg" alt=""><!-- 背景图片--> 3 <div class="cover cover2"><!-- 遮盖层--> 4 <div class="innerB

原生js吸顶式导航条

<!--吸顶式导航条--><nav class="nav"> <div> <a href="javascript: return false"><img src="n.jpg" ></a> <div class="topNav"> <div> <input type="text" placeholder=&