Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 子项匹配\u父项忽略具有viewdraghelper的自定义视图中的父项_Java_Android_Viewgroup_Viewdraghelper - Fatal编程技术网

Java 子项匹配\u父项忽略具有viewdraghelper的自定义视图中的父项

Java 子项匹配\u父项忽略具有viewdraghelper的自定义视图中的父项,java,android,viewgroup,viewdraghelper,Java,Android,Viewgroup,Viewdraghelper,我最近一直在研究自定义视图,并试图从此处的教程中得出一个具体示例: 我将添加相关代码,以防止死链接导致信息丢失。本教程的作者解释了如何创建一个类似于YouTube的android应用程序播放器行为的ViewDragHelper,以下是他提供的代码 activity\u main.xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="

我最近一直在研究自定义视图,并试图从此处的教程中得出一个具体示例:

我将添加相关代码,以防止死链接导致信息丢失。本教程的作者解释了如何创建一个类似于YouTube的android应用程序播放器行为的ViewDragHelper,以下是他提供的代码

activity\u 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>
作者指出,
onLayout
onMeasure
写得很糟糕,我认为这些(或其中一个)可能是其中一个孩子出现问题的原因

为了实现我的目标,我将
mDescView
替换为
Framelayout
视图,其中包含相应的
TextView
。它们都将其高度设置为
match\u parent
,并且父级(
mDescView
)确实正确设置了其高度,但其子级(
TextView
内部
mDescView
)忽略父级高度并拉伸以使其高度与屏幕高度(或自定义视图高度)相等。这是一个问题,因为
mDescView
儿童永远不会通过
match\u parent
根据父母正确调整他们的身高,我已经寻找了好几天的解决方案,但没有找到任何解决方案,通过研究,我找不到发生这种情况的原因

这是此问题的结果,请注意
TextView
高度如何大于其父级
mDescView
,尽管两者的高度都设置为
match\u parent

所以我的问题是,我怎样才能让父母(或任何父母)的孩子(孩子)像他们应该的那样匹配他们父母的身高


作为一项附加要求,如果可能的话,是否有人能解释为什么作者认为他的一些方法不是最好/正确的方法,以及如何正确/更好地执行这些方法。

我终于纠正了这个问题,尽管我仍然不知道这样做是否正确。我的解决方案是在
onLayout
我还将此设置为仅在第一次调用此方法时运行,因此特定语句仅在第一次运行时运行一次(当
firstRun
true
时)

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