最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android 仿淘寶、京東商品詳情頁(yè)向上拖動(dòng)查看圖文詳情控件DEMO詳解

 更新時(shí)間:2016年09月04日 09:48:21   作者:qifengdeqingchen  
本文給大家介紹android 仿淘寶、京東商品詳情頁(yè)向上拖動(dòng)查看圖文詳情控件DEMO詳解,使用兩個(gè)scrollView,兩個(gè)scrollView 豎直排列,通過(guò)自定義viewGroup來(lái)控制兩個(gè)scrollView的豎直排列,以及滑動(dòng)事件的處理。對(duì)android 拖動(dòng)查看圖文詳情知識(shí)感興趣的朋友一起學(xué)習(xí)吧

一、淘寶商品詳情頁(yè)效果

我們的效果

二、實(shí)現(xiàn)思路

     使用兩個(gè)scrollView,兩個(gè)scrollView 豎直排列,通過(guò)自定義viewGroup來(lái)控制兩個(gè)scrollView的豎直排列,以及滑動(dòng)事件的處理。如下圖

三、具體實(shí)現(xiàn)

1、繼承viewGroup自定義布局View 重寫(xiě)onMeasure()和onLayout方法,在onLayout方法中完成對(duì)兩個(gè)子ScrollView的豎直排列布局,代碼如下:
布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 tools:context="com.baoyunlong.view.pulluptoloadmore.MainActivity"> 
 <com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:orientation="vertical"> 
  <com.baoyunlong.view.pulluptoloadmore.MyScrollView 
   android:layout_width="match_parent" 
   android:layout_height="match_parent" 
   android:fillViewport="true"> 
   <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 
    <ImageView 
     android:scaleType="fitXY" 
     android:src="@drawable/a1" 
     android:layout_width="match_parent" 
     android:layout_height="180dp" /> 
    <TextView 
     android:text="這里是標(biāo)題" 
     android:textSize="18dp" 
     android:layout_marginRight="10dp" 
     android:layout_marginLeft="10dp" 
     android:layout_marginTop="10dp" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 
    <TextView 
     android:layout_marginTop="10dp" 
     android:text="子標(biāo)題" 
     android:layout_marginLeft="10dp" 
     android:layout_marginRight="10dp" 
     android:textSize="18dp" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 
    .............. 
    <LinearLayout 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:gravity="bottom" 
     android:layout_width="match_parent"> 
     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:height="50dp" 
      android:background="#b11" 
      android:gravity="center" 
      android:text="繼續(xù)拖動(dòng)查看圖文詳情" 
      android:textColor="#000" /> 
    </LinearLayout> 
   </LinearLayout> 
  </com.baoyunlong.view.pulluptoloadmore.MyScrollView> 
  <com.baoyunlong.view.pulluptoloadmore.MyScrollView 
   android:layout_width="match_parent" 
   android:layout_height="match_parent" 
   android:fillViewport="true"> 
   <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:gravity="center" 
    android:orientation="vertical"> 
    <ImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@drawable/a1" /> 
    <ImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@drawable/a3" /> 
    ......... 
   </LinearLayout> 
</com.baoyunlong.view.pulluptoloadmore.MyScrollView> </com.baoyunlong.view.pulluptoloadmore.PullUpToLoadMore> 
</RelativeLayout> 

代碼:

public class PullUpToLoadMore extends ViewGroup { 
 public PullUpToLoadMore(Context context) { 
  super(context); 
 } 
 public PullUpToLoadMore(Context context, AttributeSet attrs) { 
  super(context, attrs); 
 } 
 public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) { 
  super(context, attrs, defStyleAttr); 
 } 
 @Override 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
  super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
  measureChildren(widthMeasureSpec, heightMeasureSpec); 
 } 
 @Override 
 protected void onLayout(boolean changed, int l, int t, int r, int b) { 
  int childCount = getChildCount(); 
  int childTop = t; 
  for (int i = 0; i < childCount; i++) { 
   View child = getChildAt(i); 
   child.layout(l, childTop, r, childTop + child.getMeasuredHeight()); 
   childTop += child.getMeasuredHeight(); 
  } 
 } 
} 

2、處理滑動(dòng)事件   

   規(guī)則如下 :     

   (1)、當(dāng)處于第一屏?xí)r 第一個(gè)ScrollView已經(jīng)滑動(dòng)到底部并且滑動(dòng)方向是往上滑動(dòng),這個(gè)時(shí)候滑動(dòng)事件應(yīng)該交給父view處理也就是攔截事件讓onInterceptTouchEvent返回true.然后父view通過(guò)scrollBy()方法滾動(dòng),顯示出第二個(gè)scrollView。   

   (2)、當(dāng)處于第二屏?xí)r 第二個(gè)ScrollView已經(jīng)滑動(dòng)到頂部并且滑動(dòng)方向是往下滑動(dòng),這個(gè)時(shí)候滑動(dòng)事件交給父view處理,根據(jù)滑動(dòng)事件顯示出第一個(gè)ScrollView。

   (3)、當(dāng)手指離開(kāi)屏幕時(shí),根據(jù)滑動(dòng)速度來(lái)決定是回彈到第一個(gè)ScrollView還是第二個(gè)ScrollView,通過(guò)VelocityTracker來(lái)獲取滑動(dòng)速度。

3、一些細(xì)節(jié)的處理

        (1)、如果仔細(xì)看觀察淘寶的實(shí)現(xiàn)效果你會(huì)發(fā)現(xiàn),當(dāng)你滑動(dòng)到剛剛看到 “繼續(xù)拖動(dòng),查看圖文詳情”的時(shí)候,手指抬起,然后再按下重新向上拖動(dòng)你會(huì)發(fā)現(xiàn),第二頁(yè)并不會(huì)劃出來(lái),而是停留在了“繼續(xù)拖動(dòng),查看圖文詳情”的底部,京東的效果也是一樣。這樣用戶(hù)體驗(yàn)不太好,我們來(lái)優(yōu)化一下。其實(shí)通過(guò)查看ScrollView的源碼可以看出來(lái),這是因?yàn)镾crollView類(lèi)的onTouchEvent方法的默認(rèn)實(shí)現(xiàn),調(diào)用了parent.requestDisallowInterceptTouchEvent(true)方法 阻止了我們攔截事件,導(dǎo)致我們父view的onInterceptTouchEvent方法無(wú)法執(zhí)行,也就攔截不到事件,攔截不到事件我們的onTouchEvent就無(wú)法執(zhí)行,onTouchEvent無(wú)法執(zhí)行,我們寫(xiě)在onTouchEvent里面的滾動(dòng)邏輯就執(zhí)行不到了,導(dǎo)致了上面我們看到的劃不動(dòng)的效果。解決方法就是,我們需要重寫(xiě)dispatchTouchEvent()方法,防止子view干擾我們,這樣我們滑動(dòng)的時(shí)候就可以一氣呵成了。代碼如下:

@Override 
 public boolean dispatchTouchEvent(MotionEvent ev) { 
  //防止子View禁止父view攔截事件 
  this.requestDisallowInterceptTouchEvent(false); 
  return super.dispatchTouchEvent(ev); 
 } 

      (2)、監(jiān)聽(tīng)ScrollView滑動(dòng)事件的問(wèn)題

          ScrollView沒(méi)有提供滾動(dòng)事件的監(jiān)聽(tīng)方法,也就沒(méi)法判斷是否滾動(dòng)到了頂部,或者底部,這里我們繼承ScrollView 自己實(shí)現(xiàn)滾動(dòng)事件監(jiān)聽(tīng)。

/** 
 * Created by baoyunlong on 16/6/8. 
 */ 
public class MyScrollView extends ScrollView { 
 private static String TAG=MyScrollView.class.getName(); 
 public void setScrollListener(ScrollListener scrollListener) { 
  this.mScrollListener = scrollListener; 
 } 
 private ScrollListener mScrollListener; 
 public MyScrollView(Context context) { 
  super(context); 
 } 
 public MyScrollView(Context context, AttributeSet attrs) { 
  super(context, attrs); 
 } 
 public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) { 
  super(context, attrs, defStyleAttr); 
 } 
 @Override 
 public boolean onTouchEvent(MotionEvent ev) { 
  switch (ev.getAction()){ 
   case MotionEvent.ACTION_MOVE: 
    if(mScrollListener!=null){ 
     int contentHeight=getChildAt(0).getHeight(); 
     int scrollHeight=getHeight(); 
     int scrollY=getScrollY(); 
     mScrollListener.onScroll(scrollY); 
     if(scrollY+scrollHeight>=contentHeight||contentHeight<=scrollHeight){ 
      mScrollListener.onScrollToBottom(); 
     }else { 
      mScrollListener.notBottom(); 
     } 
     if(scrollY==0){ 
      mScrollListener.onScrollToTop(); 
     } 
    } 
    break; 
  } 
  boolean result=super.onTouchEvent(ev); 
  requestDisallowInterceptTouchEvent(false); 
  return result; 
 } 
 public interface ScrollListener{ 
  void onScrollToBottom(); 
  void onScrollToTop(); 
  void onScroll(int scrollY); 
  void notBottom(); 
 } 

4、完整代碼如下

/** 
 * Created by baoyunlong on 16/6/8. 
 */ 
public class PullUpToLoadMore extends ViewGroup { 
 public static String TAG = PullUpToLoadMore.class.getName(); 
 MyScrollView topScrollView, bottomScrollView; 
 VelocityTracker velocityTracker = VelocityTracker.obtain(); 
 Scroller scroller = new Scroller(getContext()); 
 int currPosition = 0; 
 int position1Y; 
 int lastY; 
 public int scaledTouchSlop;//最小滑動(dòng)距離 
 int speed = 200; 
 boolean isIntercept; 
 public boolean bottomScrollVIewIsInTop = false; 
 public boolean topScrollViewIsBottom = false; 
 public PullUpToLoadMore(Context context) { 
  super(context); 
  init(); 
 } 
 public PullUpToLoadMore(Context context, AttributeSet attrs) { 
  super(context, attrs); 
  init(); 
 } 
 public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) { 
  super(context, attrs, defStyleAttr); 
  init(); 
 } 
 private void init() { 
  post(new Runnable() { 
   @Override 
   public void run() { 
    topScrollView = (MyScrollView) getChildAt(0); 
    bottomScrollView = (MyScrollView) getChildAt(1); 
    topScrollView.setScrollListener(new MyScrollView.ScrollListener() { 
     @Override 
     public void onScrollToBottom() { 
      topScrollViewIsBottom = true; 
     } 
     @Override 
     public void onScrollToTop() { 
     } 
     @Override 
     public void onScroll(int scrollY) { 
     } 
     @Override 
     public void notBottom() { 
      topScrollViewIsBottom = false; 
     } 
    }); 
    bottomScrollView.setScrollListener(new MyScrollView.ScrollListener() { 
     @Override 
     public void onScrollToBottom() { 
     } 
     @Override 
     public void onScrollToTop() { 
     } 
     @Override 
     public void onScroll(int scrollY) { 
      if (scrollY == 0) { 
       bottomScrollVIewIsInTop = true; 
      } else { 
       bottomScrollVIewIsInTop = false; 
      } 
     } 
     @Override 
     public void notBottom() { 
     } 
    }); 
    position1Y = topScrollView.getBottom(); 
    scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); 
   } 
  }); 
 } 
 @Override 
 public boolean dispatchTouchEvent(MotionEvent ev) { 
  //防止子View禁止父view攔截事件 
  this.requestDisallowInterceptTouchEvent(false); 
  return super.dispatchTouchEvent(ev); 
 } 
 @Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
  int y = (int) ev.getY(); 
  switch (ev.getAction()) { 
   case MotionEvent.ACTION_DOWN: 
    lastY = y; 
    break; 
   case MotionEvent.ACTION_MOVE: 
    //判斷是否已經(jīng)滾動(dòng)到了底部 
    if (topScrollViewIsBottom) { 
     int dy = lastY - y; 
     //判斷是否是向上滑動(dòng)和是否在第一屏 
     if (dy > 0 && currPosition == 0) { 
      if (dy >= scaledTouchSlop) { 
       isIntercept = true;//攔截事件 
       lastY=y; 
      } 
     } 
    } 
    if (bottomScrollVIewIsInTop) { 
     int dy = lastY - y; 
     //判斷是否是向下滑動(dòng)和是否在第二屏 
     if (dy < 0 && currPosition == 1) { 
      if (Math.abs(dy) >= scaledTouchSlop) { 
       isIntercept = true; 
      } 
     } 
    } 
    break; 
  } 
  return isIntercept; 
 } 
 @Override 
 public boolean onTouchEvent(MotionEvent event) { 
  int y = (int) event.getY(); 
  velocityTracker.addMovement(event); 
  switch (event.getAction()) { 
   case MotionEvent.ACTION_MOVE: 
    int dy = lastY - y; 
    if (getScrollY() + dy < 0) { 
     dy = getScrollY() + dy + Math.abs(getScrollY() + dy); 
    } 
    if (getScrollY() + dy + getHeight() > bottomScrollView.getBottom()) { 
     dy = dy - (getScrollY() + dy - (bottomScrollView.getBottom() - getHeight())); 
    } 
    scrollBy(0, dy); 
    break; 
   case MotionEvent.ACTION_UP: 
    isIntercept = false; 
    velocityTracker.computeCurrentVelocity(1000); 
    float yVelocity = velocityTracker.getYVelocity(); 
    if (currPosition == 0) { 
     if (yVelocity < 0 && yVelocity < -speed) { 
      smoothScroll(position1Y); 
      currPosition = 1; 
     } else { 
      smoothScroll(0); 
     } 
    } else { 
     if (yVelocity > 0 && yVelocity > speed) { 
      smoothScroll(0); 
      currPosition = 0; 
     } else { 
      smoothScroll(position1Y); 
     } 
    } 
    break; 
  } 
  lastY = y; 
  return true; 
 } 
 @Override 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
  super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
  measureChildren(widthMeasureSpec, heightMeasureSpec); 
 } 
 @Override 
 protected void onLayout(boolean changed, int l, int t, int r, int b) { 
  int childCount = getChildCount(); 
  int childTop = t; 
  for (int i = 0; i < childCount; i++) { 
   View child = getChildAt(i); 
   child.layout(l, childTop, r, childTop + child.getMeasuredHeight()); 
   childTop += child.getMeasuredHeight(); 
  } 
 } 
 //通過(guò)Scroller實(shí)現(xiàn)彈性滑動(dòng) 
 private void smoothScroll(int tartY) { 
  int dy = tartY - getScrollY(); 
  scroller.startScroll(getScrollX(), getScrollY(), 0, dy); 
  invalidate(); 
 } 
 @Override 
 public void computeScroll() { 
  if (scroller.computeScrollOffset()) { 
   scrollTo(scroller.getCurrX(), scroller.getCurrY()); 
   postInvalidate(); 
  } 
 } 
} 

源碼:

github地址

以上所述是小編給大家介紹的Android 仿淘寶、京東商品詳情頁(yè)向上拖動(dòng)查看圖文詳情控件DEMO詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論

阿鲁科尔沁旗| 永胜县| 张家川| 东乡族自治县| 南丰县| 加查县| 榕江县| 抚宁县| 营山县| 通州区| 叶城县| 建德市| 鄂托克前旗| 靖宇县| 水富县| 年辖:市辖区| 云龙县| 新河县| 霍邱县| 鹤山市| 扎囊县| 白河县| 精河县| 和田市| 聂拉木县| 富平县| 城市| 兴义市| 江都市| 富锦市| 塘沽区| 抚宁县| 东方市| 邛崃市| 霍城县| SHOW| 新化县| 莒南县| 南昌县| 东港市| 道孚县|