Heim  >  Artikel  >  Java  >  Android-Nachahmung Taobao, Jingdong-Produktdetailseite nach oben ziehen, um detaillierte Erklärung der grafischen Detailsteuerung DEMO anzuzeigen

Android-Nachahmung Taobao, Jingdong-Produktdetailseite nach oben ziehen, um detaillierte Erklärung der grafischen Detailsteuerung DEMO anzuzeigen

高洛峰
高洛峰Original
2017-02-08 17:10:332077Durchsuche

Dieser Artikel stellt Ihnen die detaillierte DEMO-Erklärung der Produktdetailseite von Android-Imitationen von Taobao und JD.com vor, indem Sie nach oben ziehen, um grafische Details anzuzeigen, und die beiden ScrollViews sind vertikal angeordnet zwei scrollViews werden durch Anpassen der viewGroup-Anordnung und der Behandlung von Gleitereignissen gesteuert. Freunde, die sich für das Ziehen interessieren, um Bild- und Textdetails in Android anzuzeigen, sollten gemeinsam lernen

1. Taobao-Produktdetailseiteneffekt

Android 仿淘宝、京东商品详情页向上拖动查看图文详情控件DEMO详解

Unsere Wirkung

Android 仿淘宝、京东商品详情页向上拖动查看图文详情控件DEMO详解

2. Umsetzungsideen

Verwendung zwei scrollViews, zwei scrollViews sind vertikal angeordnet, und die vertikale Anordnung der beiden scrollViews wird durch Anpassen der viewGroup sowie durch die Verarbeitung von Gleitereignissen gesteuert. Wie unten gezeigt

3. Spezifische Implementierung

1. Erben Sie das benutzerdefinierte ViewGroup-Layout und überschreiben Sie die Methoden onMeasure() und onLayout Die onLayout-Methode Vervollständigen Sie das vertikale Layout der beiden Sub-ScrollViews. Der Code lautet wie folgt:
Layoutdatei:

<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="这里是标题" 
     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="子标题" 
     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="继续拖动查看图文详情" 
      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>

Code:

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. Umgang mit Gleitereignissen

Die Regeln lauten wie folgt:

(1), wenn in Auf dem ersten Bildschirm ist die erste ScrollView nach unten gerutscht und die Schieberichtung ist nach oben. Zu diesem Zeitpunkt sollte das Schiebeereignis zur Verarbeitung an die übergeordnete Ansicht übergeben werden Das Ereignis sollte abgefangen werden und onInterceptTouchEvent gibt true zurück. Dann scrollt die übergeordnete Ansicht durch die scrollBy()-Methode und zeigt die zweite scrollView an.

(2) Wenn auf dem zweiten Bildschirm die zweite ScrollView nach oben verschoben wurde und die Schieberichtung nach unten verschoben wird, wird das Schiebeereignis zur Verarbeitung an die übergeordnete Ansicht übergeben Das erste wird entsprechend dem Sliding-Ereignis angezeigt.

(3) Wenn der Finger den Bildschirm verlässt, entscheiden Sie basierend auf der Gleitgeschwindigkeit, ob Sie zur ersten ScrollView oder zur zweiten ScrollView zurückkehren möchten, und erhalten Sie die Gleitgeschwindigkeit über VelocityTracker.

3. Verarbeitung einiger Details

(1) Wenn Sie den Implementierungseffekt von Taobao sorgfältig beobachten, werden Sie feststellen, dass Sie an den Punkt gelangen, an dem Sie gerade „Weiterziehen, anzeigen“ gesehen haben Um die Details des Bilds und des Textes anzuzeigen, heben Sie Ihren Finger an, drücken Sie und ziehen Sie ihn erneut nach oben. Sie werden feststellen, dass die zweite Seite nicht herausgezogen wird, sondern am unteren Rand von „Ziehen Sie weiter, um Bild- und Textdetails anzuzeigen“ angezeigt wird ". Der Effekt von JD.com Das Gleiche. Diese Benutzererfahrung ist nicht sehr gut. Lassen Sie uns sie optimieren. Wenn wir uns den Quellcode von ScrollView ansehen, können wir tatsächlich erkennen, dass dies daran liegt, dass die Standardimplementierung der onTouchEvent-Methode der ScrollView-Klasse die Methode parent.requestDisallowInterceptTouchEvent(true) aufruft, um zu verhindern, dass wir das Ereignis abfangen, was zu onInterceptTouchEvent führt Die Methode unserer übergeordneten Ansicht kann nicht ausgeführt werden und wird daher nicht abgefangen. Wenn das Ereignis nicht empfangen werden kann, kann unser OnTouchEvent nicht ausgeführt werden im Unfähigkeit-zu-Scrollen-Effekt, wie wir oben gesehen haben. Die Lösung besteht darin, dass wir die Methode „dispatchTouchEvent()“ neu schreiben müssen, um zu verhindern, dass die Unteransicht uns stört, sodass wir dies auf einmal tun können, wenn wir gleiten. Der Code lautet wie folgt:

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

(2) Probleme bei der Überwachung von ScrollView-Schiebeereignissen

ScrollView bietet keine Überwachungsmethode für Scrolling-Ereignisse Es gibt keine Möglichkeit zu beurteilen, ob das Scrollen den oberen oder unteren Rand erreicht hat. Hier erben wir ScrollView und implementieren selbst die Scroll-Ereignisüberwachung.

/** 
 * 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. Der vollständige Code lautet wie folgt:

/** 
 * 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;//最小滑动距离 
 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: 
    //判断是否已经滚动到了底部 
    if (topScrollViewIsBottom) { 
     int dy = lastY - y; 
     //判断是否是向上滑动和是否在第一屏 
     if (dy > 0 && currPosition == 0) { 
      if (dy >= scaledTouchSlop) { 
       isIntercept = true;//拦截事件 
       lastY=y; 
      } 
     } 
    } 
    if (bottomScrollVIewIsInTop) { 
     int dy = lastY - y; 
     //判断是否是向下滑动和是否在第二屏 
     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(); 
  } 
 } 
 //通过Scroller实现弹性滑动 
 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(); 
  } 
 } 
}

Quellcode:

Github-Adresse

Das Obige ist die vom Herausgeber eingeführte Android-Imitationsseite für Taobao- und JD-Produktdetails. Ziehen Sie nach oben, um die DEMO mit grafischen Details anzuzeigen. Ich hoffe, dass es für Sie hilfreich ist. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Herausgeber wird Ihnen rechtzeitig antworten. Ich möchte mich auch bei Ihnen allen für Ihre Unterstützung der chinesischen PHP-Website bedanken!

Für weitere Android-Imitationsseiten mit Taobao- und JD.com-Produktdetails ziehen Sie nach oben, um grafische Details anzuzeigen und die DEMO für detaillierte Erklärungen zu steuern. Weitere Informationen zu verwandten Artikeln finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn