2017-02-01 11 views
0
나는 최근 사용자 정의보기를 공부 한

와 사용자 지정보기에 부모를 무시하고 하나의 특정 예는 여기에 튜토리얼에서 해결하려고 노력 match_parent : http://flavienlaurent.com/blog/2013/08/28/each-navigation-drawer-hides-a-viewdraghelper/아이들은 viewdraghelper

내가 정보 손실을 방지하기 위해 관련 코드를 추가합니다 죽은 링크. 튜토리얼의 저자는 YouTube의 안드로이드 응용 프로그램 플레이어의 행동과 유사한 ViewDragHelper을 만드는 방법에 대해 설명하고 이러한 그가

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); 
    } 
} 

을 제공하는 코드입니다 저자는 onLayoutonMeasure이 잘못 쓰여 있다고 생각합니다. 이 중 하나 (또는 ​​그 중 하나)가 어린이 중 한 명과 관련된 문제의 원인 일 수 있습니다.

제 생각에는 을 TextView이 포함 된 Framelayout보기로 바꿨습니다. 둘 다 높이를 match_parent으로 설정하고 부모 (mDescView)는 높이를 올바르게 설정하지만 자녀 (TextView ~ mDescView)는 부모 높이를 무시하고 높이를 화면 높이 (또는 사용자 정의보기 높이)와 동일하게 맞 춥니 다 , 차이를 말할 수 없다). 이것은 mDescView 아이들이 부모에 따라 정확하게 신장을 조정하지 않고 match_parent을 통해 해결할 것이기 때문에 나는 며칠 동안 해결책을 찾고 있었지만 아무 것도 발견되지 않았고 연구를 통해 왜 이런 일이 일어 났는지 이유를 찾을 수 없었기 때문에 문제가된다. .

이 문제의 결과는 TextView 높이가 모두 자신의 높이가

enter image description here

그래서 내 문제가 match_parent로 설정에도 불구 부모 mDescView보다 큰 방법을 발견, 어떻게 얻을 수있는 부모님 (또는 부모님)의 자녀 (자녀)가 부모님의 키와 일치해야합니다.

추가 요청으로 저자가 자신의 방법 중 일부가 최고/올바른 방법이 아니며 올바르게/더 잘 수행되어야한다고 생각하는 이유를 설명 할 수 있습니다.

답변

0

마침내이 문제를 해결했지만 이것이 올바른 방법인지 아직 알지 못합니다. 내 솔루션은 두 뷰의 높이를 설정하는 동안 onLayout 또한이 메서드를 호출 할 때만 실행되도록 설정 했으므로 특정 문은 처음에만 한 번만 실행됩니다 (firstRuntrue 일 때)

@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); 
}