2017-02-01 5 views
0

Ich habe vor kurzem benutzerdefinierte Ansichten studiert und versucht, ein spezielles Beispiel ausrechnen aus einem Tutorial hier befindet sich zu machen: http://flavienlaurent.com/blog/2013/08/28/each-navigation-drawer-hides-a-viewdraghelper/Kinder match_parent ignorieren Eltern in benutzerdefinierte Ansicht mit viewdraghelper

Ich werde den entsprechenden Code hinzufügen Informationsverlust zu verhindern, toter Link. Der Autor des Tutorial erklärt, wie ein ViewDragHelper ähnlich wie YouTube Android App Spielerverhalten erstellen und diese sind die Codes er

vorgesehen

activity_main.xml

<FrameLayout 

    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

<ListView 
     android:id="@+id/listView" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:tag="list" 
     /> 

<com.example.vdh.YoutubeLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:id="@+id/youtubeLayout" 
     android:orientation="vertical" 
     android:visibility="visible"> 

    <TextView 
      android:id="@+id/viewHeader" 
      android:layout_width="match_parent" 
      android:layout_height="128dp" 
      android:fontFamily="sans-serif-thin" 
      android:textSize="25sp" 
      android:tag="text" 
      android:gravity="center" 
      android:textColor="@android:color/white" 
      android:background="#AD78CC"/> 

    <TextView 
      android:id="@+id/viewDesc" 
      android:tag="desc" 
      android:textSize="35sp" 
      android:gravity="center" 
      android:text="Loreum Loreum" 
      android:textColor="@android:color/white" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:background="#FF00FF"/> 

</com.example.vdh.YoutubeLayout> 

YoutubeLayout.java

public class YoutubeLayout extends ViewGroup { 

    private final ViewDragHelper mDragHelper; 

    private View mHeaderView; 
    private View mDescView; 

    private float mInitialMotionX; 
    private float mInitialMotionY; 

    private int mDragRange; 
    private int mTop; 
    private float mDragOffset; 


    public YoutubeLayout(Context context) { 
     this(context, null); 
    } 

    public YoutubeLayout(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    @Override 
    protected void onFinishInflate() { 
     mHeaderView = findViewById(R.id.viewHeader); 
     mDescView = findViewById(R.id.viewDesc); 
    } 

    public YoutubeLayout(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     mDragHelper = ViewDragHelper.create(this, 1f, new DragHelperCallback()); 
    } 

    public void maximize() { 
     smoothSlideTo(0f); 
    } 

    boolean smoothSlideTo(float slideOffset) { 
     final int topBound = getPaddingTop(); 
     int y = (int) (topBound + slideOffset * mDragRange); 

     if (mDragHelper.smoothSlideViewTo(mHeaderView, mHeaderView.getLeft(), y)) { 
      ViewCompat.postInvalidateOnAnimation(this); 
      return true; 
     } 
     return false; 
    } 

    private class DragHelperCallback extends ViewDragHelper.Callback { 

     @Override 
     public boolean tryCaptureView(View child, int pointerId) { 
      return child == mHeaderView; 
     } 

     @Override 
     public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 
      mTop = top; 

      mDragOffset = (float) top/mDragRange; 

      mHeaderView.setPivotX(mHeaderView.getWidth()); 
      mHeaderView.setPivotY(mHeaderView.getHeight()); 
      mHeaderView.setScaleX(1 - mDragOffset/2); 
      mHeaderView.setScaleY(1 - mDragOffset/2); 

      mDescView.setAlpha(1 - mDragOffset); 

      requestLayout(); 
     } 

     @Override 
     public void onViewReleased(View releasedChild, float xvel, float yvel) { 
      int top = getPaddingTop(); 
      if (yvel > 0 || (yvel == 0 && mDragOffset > 0.5f)) { 
       top += mDragRange; 
      } 
      mDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top); 
     } 

     @Override 
     public int getViewVerticalDragRange(View child) { 
      return mDragRange; 
     } 

     @Override 
     public int clampViewPositionVertical(View child, int top, int dy) { 
      final int topBound = getPaddingTop(); 
      final int bottomBound = getHeight() - mHeaderView.getHeight() - mHeaderView.getPaddingBottom(); 

      final int newTop = Math.min(Math.max(top, topBound), bottomBound); 
      return newTop; 
     } 

    } 

    @Override 
    public void computeScroll() { 
     if (mDragHelper.continueSettling(true)) { 
      ViewCompat.postInvalidateOnAnimation(this); 
     } 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     final int action = MotionEventCompat.getActionMasked(ev); 

     if ((action != MotionEvent.ACTION_DOWN)) { 
      mDragHelper.cancel(); 
      return super.onInterceptTouchEvent(ev); 
     } 

     if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { 
      mDragHelper.cancel(); 
      return false; 
     } 

     final float x = ev.getX(); 
     final float y = ev.getY(); 
     boolean interceptTap = false; 

     switch (action) { 
      case MotionEvent.ACTION_DOWN: { 
       mInitialMotionX = x; 
       mInitialMotionY = y; 
       interceptTap = mDragHelper.isViewUnder(mHeaderView, (int) x, (int) y); 
       break; 
      } 

      case MotionEvent.ACTION_MOVE: { 
       final float adx = Math.abs(x - mInitialMotionX); 
       final float ady = Math.abs(y - mInitialMotionY); 
       final int slop = mDragHelper.getTouchSlop(); 
       if (ady > slop && adx > ady) { 
        mDragHelper.cancel(); 
        return false; 
       } 
      } 
     } 

     return mDragHelper.shouldInterceptTouchEvent(ev) || interceptTap; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     mDragHelper.processTouchEvent(ev); 

     final int action = ev.getAction(); 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     boolean isHeaderViewUnder = mDragHelper.isViewUnder(mHeaderView, (int) x, (int) y); 
     switch (action & MotionEventCompat.ACTION_MASK) { 
      case MotionEvent.ACTION_DOWN: { 
       mInitialMotionX = x; 
       mInitialMotionY = y; 
       break; 
      } 

      case MotionEvent.ACTION_UP: { 
       final float dx = x - mInitialMotionX; 
       final float dy = y - mInitialMotionY; 
       final int slop = mDragHelper.getTouchSlop(); 
       if (dx * dx + dy * dy < slop * slop && isHeaderViewUnder) { 
        if (mDragOffset == 0) { 
         smoothSlideTo(1f); 
        } else { 
         smoothSlideTo(0f); 
        } 
       } 
       break; 
      } 
     } 


     return isHeaderViewUnder && isViewHit(mHeaderView, (int) x, (int) y) || isViewHit(mDescView, (int) x, (int) y); 
    } 


    private boolean isViewHit(View view, int x, int y) { 
     int[] viewLocation = new int[2]; 
     view.getLocationOnScreen(viewLocation); 
     int[] parentLocation = new int[2]; 
     this.getLocationOnScreen(parentLocation); 
     int screenX = parentLocation[0] + x; 
     int screenY = parentLocation[1] + y; 
     return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth() && 
       screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     measureChildren(widthMeasureSpec, heightMeasureSpec); 

     int maxWidth = MeasureSpec.getSize(widthMeasureSpec); 
     int maxHeight = MeasureSpec.getSize(heightMeasureSpec); 

     setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0), 
       resolveSizeAndState(maxHeight, heightMeasureSpec, 0)); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     mDragRange = getHeight() - mHeaderView.getHeight(); 

     mHeaderView.layout(
       0, 
       mTop, 
       r, 
       mTop + mHeaderView.getMeasuredHeight()); 

     mDescView.layout(
       0, 
       mTop + mHeaderView.getMeasuredHeight(), 
       r, 
       mTop + b); 
    } 
} 

Die Autor stellt fest, dass onLayout und onMeasure schlecht geschrieben sind und ich nehme an diese (oder einer von ihnen) könnte die Ursache eines Problems mit einem der Kinder sein.

Für mein Ziel, ersetzte ich die mDescView mit einer Framelayout Ansicht, die die entsprechenden TextView enthält. Beide haben ihre Höhe auf match_parent und das übergeordnete (mDescView) legt seine Höhe korrekt, aber seine Kinder (TextView innerhalb mDescView) ignorieren die übergeordnete Höhe und strecken, um ihre Höhe gleich der Bildschirmhöhe (oder der benutzerdefinierten Ansichtshöhe , kann den Unterschied nicht erkennen). Dies ist ein Problem, weil die mDescView Kinder nie ihre Höhe korrekt nach dem Eltern durch anpassen und ich suchte nach einer Lösung für Tage, aber keine wurde gefunden und durch Forschung konnte ich keinen Grund finden, warum dies geschah .

Dies ist das Ergebnis dieses Problems feststellen, wie die TextView Höhe ist größer als ihre Mutter mDescView trotz beide haben ihre Höhe auf match_parent

enter image description here

Also mein Problem ist, wie kann ich die Kind (Kinder) dieses Elternteils (oder jeder Elternteil), um die Größe ihrer Eltern so anzupassen, wie sie es sollten.

Als zusätzliche Anfrage, wenn möglich, kann jemand erklären, warum der Autor denkt, dass einige seiner Methoden nicht die besten/richtigen sind und wie sie stattdessen richtig/besser gemacht werden sollten.

Antwort

0

Ich habe dieses Problem endlich behoben, obwohl mir immer noch nicht bewusst ist, ob dies der richtige Weg ist. Meine Lösung war, die Höhe beider Ansichten während onLayout zu setzen Ich habe auch festgelegt, dass nur beim ersten Aufruf dieser Methode ausgeführt wird, so dass die spezifische Anweisung nur einmal ausgeführt wird und nur beim ersten Mal (firstRun

)
@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    mDragRange = getHeight() - mHeaderView.getHeight(); 

    if (firstRun) { 
     firstRun = false; 
     mDescView.getLayoutParams().height = getHeight() - mHeaderView.getMeasuredHeight(); 
    } 

    mHeaderView.layout(
      0, 
      mTop, 
      r, 
      mTop + mHeaderView.getMeasuredHeight()); 

    mDescView.layout(
      0, 
      mTop + mHeaderView.getMeasuredHeight(), 
      r, 
      mTop + b); 
} 
Verwandte Themen