框架学习三:仿美团购买框悬浮效果
来源:互联网 发布:达芬奇调色mac破解版 编辑:程序博客网 时间:2024/05/16 07:58
转自夏神blog:http://blog.csdn.net/xiaanming/article/details/17761431
一、大概了解下
美团网用的是Scrolling Tricks,但是只支持API11以上。夏神实现了的修改版可适用API11以下版本,说下夏神的思路:首先对ScrollView滚动监听,直接在OnScrollChanged()中就能获得滚动的Y值。
二、实现
第一步:界面引入自定义的ScrollView。注意需要两个地方,一个要固定的位置,另一个是实际显示的位置。第二步:添加自定义ScrollView的滚动监听事件。第三步:设置当主布局的状态或者控件的可见性发生改变时回调接口。
三、代码
1、自定义的ScrollView
package com.example.myscroll;import android.widget.ScrollView;import android.content.Context; import android.util.AttributeSet; /** * @blog http://blog.csdn.net/xiaanming * * @author xiaanming * */ public class MyScrollView extends ScrollView {private OnScrollListener onScrollListener; public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 设置滚动接口 * @param onScrollListener */ public void setOnScrollListener(OnScrollListener onScrollListener) { this.onScrollListener = onScrollListener; } @Override public int computeVerticalScrollRange() { return super.computeVerticalScrollRange(); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if(onScrollListener != null){ onScrollListener.onScroll(t); } } /** * * 滚动的回调接口 * * @author xiaanming * */ public interface OnScrollListener{ /** * 回调方法, 返回MyScrollView滑动的Y方向距离 * @param scrollY * 、 */ public void onScroll(int scrollY); } }界面中引入:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parent_layout" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="45dip" android:scaleType="centerCrop" android:src="@drawable/navigation_bar" /> <com.example.myscroll.MyScrollView android:id="@+id/scrollView" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:id="@+id/iamge" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/pic" android:scaleType="centerCrop" /> <include android:id="@+id/buy" layout="@layout/buy_layout" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/one" android:scaleType="centerCrop" /> </LinearLayout> <include android:id="@+id/top_buy_layout" layout="@layout/buy_layout" /> </FrameLayout> </com.example.myscroll.MyScrollView> </LinearLayout>2、代码实现
public class MainActivity extends Activity implements OnScrollListener {/** * 自定义的MyScrollView */ private MyScrollView myScrollView; /** * 在MyScrollView里面的购买布局 */ private LinearLayout mBuyLayout; /** * 位于顶部的购买布局 */ private LinearLayout mTopBuyLayout; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myScrollView = (MyScrollView) findViewById(R.id.scrollView); mBuyLayout = (LinearLayout) findViewById(R.id.buy); mTopBuyLayout = (LinearLayout) findViewById(R.id.top_buy_layout); myScrollView.setOnScrollListener(this); //当布局的状态或者控件的可见性发生改变回调的接口 findViewById(R.id.parent_layout).getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //这一步很重要,使得上面的购买布局和下面的购买布局重合 onScroll(myScrollView.getScrollY()); } }); }@Overridepublic void onScroll(int scrollY) {int mBuyLayout2ParentTop = Math.max(scrollY, mBuyLayout.getTop()); mTopBuyLayout.layout(0, mBuyLayout2ParentTop, mTopBuyLayout.getWidth(), mBuyLayout2ParentTop + mTopBuyLayout.getHeight()); }}
四、含有多个购买布局的效果
即下一个购买布局将上一个购买布局顶上去,使用方法也简单:引入自定义ScrollView,不同于上面的;然后将需要设置的布局设置Tag为sticky。如:
<FrameLayout android:layout_width="fill_parent" android:layout_height="100dip" android:background="#ff00ffff" android:tag="sticky" > <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Button" /> </FrameLayout>
自定义ScrollView:
package com.example.stikyscrollview;import java.util.LinkedList;import java.util.List;import android.content.Context;import android.graphics.Canvas;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.ScrollView;public class StickyScrollView extends ScrollView {private static final String STICKY = "sticky";private View mCurrentStickyView ;private Drawable mShadowDrawable;private List<View> mStickyViews;private int mStickyViewTopOffset;private int defaultShadowHeight = 10;private float density;private boolean redirectTouchToStickyView;/** * 当点击Sticky的时候,实现某些背景的渐变 */private Runnable mInvalidataRunnable = new Runnable() {@Overridepublic void run() {if(mCurrentStickyView != null){int left = mCurrentStickyView.getLeft();int top = mCurrentStickyView.getTop();int right = mCurrentStickyView.getRight();int bottom = getScrollY() + (mCurrentStickyView.getHeight() + mStickyViewTopOffset);invalidate(left, top, right, bottom);}postDelayed(this, 16);}};public StickyScrollView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public StickyScrollView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mShadowDrawable = context.getResources().getDrawable(R.drawable.sticky_shadow_default);mStickyViews = new LinkedList<View>();density = context.getResources().getDisplayMetrics().density;}/** * 找到设置tag的View * @param viewGroup */private void findViewByStickyTag(ViewGroup viewGroup){int childCount = ((ViewGroup)viewGroup).getChildCount();for(int i=0; i<childCount; i++){View child = viewGroup.getChildAt(i);if(getStringTagForView(child).contains(STICKY)){mStickyViews.add(child);}if(child instanceof ViewGroup){findViewByStickyTag((ViewGroup)child);}}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if(changed){findViewByStickyTag((ViewGroup)getChildAt(0));}showStickyView();}@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);showStickyView();}/** * */private void showStickyView(){View curStickyView = null;View nextStickyView = null;for(View v : mStickyViews){int topOffset = v.getTop() - getScrollY();if(topOffset <= 0){if(curStickyView == null || topOffset > curStickyView.getTop() - getScrollY()){curStickyView = v;}}else{if(nextStickyView == null || topOffset < nextStickyView.getTop() - getScrollY()){nextStickyView = v;}}}if(curStickyView != null){mStickyViewTopOffset = nextStickyView == null ? 0 : Math.min(0, nextStickyView.getTop() - getScrollY() - curStickyView.getHeight());mCurrentStickyView = curStickyView;post(mInvalidataRunnable);}else{mCurrentStickyView = null;removeCallbacks(mInvalidataRunnable);}}private String getStringTagForView(View v){Object tag = v.getTag();return String.valueOf(tag);}/** * 将sticky画出来 */@Overrideprotected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);if(mCurrentStickyView != null){//先保存起来canvas.save();//将坐标原点移动到(0, getScrollY() + mStickyViewTopOffset)canvas.translate(0, getScrollY() + mStickyViewTopOffset);if(mShadowDrawable != null){int left = 0;int top = mCurrentStickyView.getHeight() + mStickyViewTopOffset;int right = mCurrentStickyView.getWidth();int bottom = top + (int)(density * defaultShadowHeight + 0.5f);mShadowDrawable.setBounds(left, top, right, bottom);mShadowDrawable.draw(canvas);}canvas.clipRect(0, mStickyViewTopOffset, mCurrentStickyView.getWidth(), mCurrentStickyView.getHeight());mCurrentStickyView.draw(canvas);//重置坐标原点参数canvas.restore();}}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {if(ev.getAction() == MotionEvent.ACTION_DOWN){redirectTouchToStickyView = true;}if(redirectTouchToStickyView){redirectTouchToStickyView = mCurrentStickyView != null;if(redirectTouchToStickyView){redirectTouchToStickyView = ev.getY() <= (mCurrentStickyView.getHeight() + mStickyViewTopOffset)&& ev.getX() >= mCurrentStickyView.getLeft()&& ev.getX() <= mCurrentStickyView.getRight();}}if (redirectTouchToStickyView) {ev.offsetLocation(0, -1 * ((getScrollY() + mStickyViewTopOffset) - mCurrentStickyView.getTop()));}return super.dispatchTouchEvent(ev);}private boolean hasNotDoneActionDown = true;@Overridepublic boolean onTouchEvent(MotionEvent ev) {if(redirectTouchToStickyView){ev.offsetLocation(0, ((getScrollY() + mStickyViewTopOffset) - mCurrentStickyView.getTop()));} if(ev.getAction()==MotionEvent.ACTION_DOWN){hasNotDoneActionDown = false;}if(hasNotDoneActionDown){MotionEvent down = MotionEvent.obtain(ev);down.setAction(MotionEvent.ACTION_DOWN);super.onTouchEvent(down);hasNotDoneActionDown = false;}if(ev.getAction()==MotionEvent.ACTION_UP || ev.getAction()==MotionEvent.ACTION_CANCEL){hasNotDoneActionDown = true;}return super.onTouchEvent(ev);}}
自定义ScrollView用到的xml:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" > <gradient android:angle="90" android:centerColor="#22222222" android:endColor="#AA222222" android:startColor="#00222222" > </gradient></shape>
0 0
- 框架学习三:仿美团购买框悬浮效果
- Android仿美团购买悬浮效果
- 安卓 仿美团网,大众点评购买框悬浮效果学习
- 仿大众点评悬浮购买框效果
- 仿美团网,大众点评购买框悬浮效果
- 美团购买框悬浮效果
- 购买栏悬浮效果实现
- Android 仿美团网,百度糯米购买框悬浮效果
- Android 仿美团网,大众点评购买框悬浮效果
- Android 仿美团网,大众点评购买框悬浮效果实现
- 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- Android 仿美团网,大众点评购买框悬浮效果之修改版
- 第一章 软件开发概述
- 经验及技巧:用MediaElement 控件实现全屏并自动旋转至横屏!
- 面试题16 反转链表
- Software Raid
- 数据挖掘、数据分析、海量数据处理的面试题---转载
- 框架学习三:仿美团购买框悬浮效果
- 设置vim配色方案
- HDU 4508 - 湫湫系列故事——减肥记I
- UVA 10422 Knights in FEN(BFS)
- Java编程思想(十三) —— 字符串之正则表达式
- NYOJ--85--有趣的数
- 爱因斯坦阶梯问题
- 最大全1子矩阵
- rake版本控制