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