框架学习三:仿美团购买框悬浮效果

来源:互联网 发布:达芬奇调色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
原创粉丝点击