11

ListViewの行をアニメーションで展開できるようにしたい。したがって、拡大しているビューの高さを知る必要があります。私は私のgetView()方法でこれを使用していArrayAdapterます:

mDetailsView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        mDetailsView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        onClickListener.setHeight(mDetailsView.getHeight());
        mDetailsView.setVisibility(View.GONE);
    }
});

これは、開始時に画面に表示されている行に対しては正常に機能しますが、下にスクロールすると、onGlobalLayout最初は表示されなかった行に対してメソッドが呼び出されません。

これらの行の高さを取得するにはどうすればよいですか?

4

4 に答える 4

14

ListViewの実装がレイアウト全体を実行しない可能性があるため、ViewTreeObserver実際に進行中のレイアウトが表示されることはありません。

私が知らない特定の電話ケースがない限り、Viewsのpostメソッドを使用して、Viewsが表示されているときにrunnableを実行できます。

mDetailsView.post(new Runnable() {
  @Override
  public void run() {
    onClickListener.setHeight(mDetailsView.getHeight());
    mDetailsView.setVisibility(View.GONE);
  }
});

編集:

getView()メソッド全体がどのようにレイアウトされているのかわかりません。問題は、私が推測しなければならないのであれば、ListView単にレイアウトを要求していないということです。代わりに、ビューごとに作業自体を実行して、処理を高速化します。あなたが試すことができるのはこれです:

public void getView(int position, View convertView, ViewGroup parent) {

  /* 
   * set your view up
   */

  mDetailsView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        mDetailsView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

        onClickListener.setHeight(mDetailsView.getHeight());
        mDetailsView.setVisibility(View.GONE);
       }
   });

   notifyDataSetInvalidated(); // Notify the ListView() and any other listeners that your views are invalid.
   return view;
}

新しい編集notifyDataSetInvalidated()通常は悪い考えで使用し、特にで使用する場合はgetView()

レイアウトを事前に測定するには、レイアウトパラメータを取得するか、存在しない場合は新しいパラメータを指定します。

    LayoutParams params = newView.getLayoutParams();
    if (params == null) {
        params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }
    final int widthSpec = MeasureSpec.makeMeasureSpec(parent.getWidth(), MeasureSpec.UNSPECIFIED);
    final int heightSpec = MeasureSpec.makeMeasureSpec(parent.getHeight(), MeasureSpec.UNSPECIFIED);
    newView.measure(widthSpec, heightSpec);
于 2013-01-14T19:37:29.630 に答える
8

ListViewまたはRecyclerViewでは、を使用する代わりに、OnGlobalLayoutListener常にを使用しますOnPreDrawListener。このコールバックは、開始時に非表示の行に対しても発生します。公式ドキュメントから:

この時点で、ツリー内のすべてのビューが測定され、フレームが与えられています。

于 2016-07-27T22:19:22.853 に答える
1

わかりました。同様の問題が発生したようです。

何らかの理由で、ListViewが途中でconvertViewを失っていた場合、ビューを新たに膨らませたときに、設定されている場合はグローバルレイアウトリスナーを呼び出していませんでした。

これが私が思いついた回避策です:

public class MyViewThatIsInList extends View {
  public MyViewThatIsInList (Context context) {
      super(context);
      ensureInited();
  }

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

  public MyViewThatIsInList (Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);

      TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyViewThatIsInList , 0, 0);
      //...
      ensureInited();
  }

  boolean isViewInited = false;
  private void init() {
      getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
          @Override
          public void onGlobalLayout() {
              //my custom helper method
              Utils.safeRemoveLayoutListener(getViewTreeObserver(), this);
              initLogic();
          }
      });
  }

  private void initLogic() {
    //...
    isViewInited = true;
  }

   private void ensureInited() {
      init();
      postDelayed(new Runnable() {
          @Override
          public void run() {
              if (!isViewInited) {
                  initLogic();
              }
          }
      }, 500);
  }

}
于 2014-07-10T19:32:35.973 に答える
1

OnGlobalLayoutListenerを使用する代わりにListViewまたはRecyclerViewでは、常にOnPreDrawListenerを使用します。このコールバックは、開始時に非表示の行に対しても発生します。公式ドキュメントから:

private void makeTextViewResizable(final TextView tv、final int maxLine、final String ExpandText、final boolean viewMore){

    try {
        if (tv.getTag() == null) {
            tv.setTag(tv.getText());
        }
        //OnGlobalLayoutListener
        ViewTreeObserver vto = tv.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

            @Override
            public boolean onPreDraw() {

                    ViewTreeObserver obs = tv.getViewTreeObserver();
                   // obs.removeGlobalOnLayoutListener((ViewTreeObserver.OnGlobalLayoutListener) mActivity);
                    obs.removeOnPreDrawListener(this);
                    if (maxLine == 0) {
                        int lineEndIndex = tv.getLayout().getLineEnd(0);
                        String text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + expandText;
                        tv.setText(text);
                        tv.setMovementMethod(LinkMovementMethod.getInstance());
                        tv.setText(
                                addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, expandText,
                                        viewMore), TextView.BufferType.SPANNABLE);
                    } else if (maxLine > 0 && tv.getLineCount() >= maxLine) {
                        int lineEndIndex = tv.getLayout().getLineEnd(maxLine - 1);
                        String text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + expandText;
                        tv.setText(text);
                        tv.setMovementMethod(LinkMovementMethod.getInstance());
                        tv.setText(
                                addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, expandText,
                                        viewMore), TextView.BufferType.SPANNABLE);
                    } else {
                        int lineEndIndex = tv.getLayout().getLineEnd(tv.getLayout().getLineCount() - 1);
                        String text = tv.getText().subSequence(0, lineEndIndex) + " " + expandText;
                        tv.setText(text);
                        tv.setMovementMethod(LinkMovementMethod.getInstance());
                        tv.setText(
                                addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, expandText,
                                        viewMore), TextView.BufferType.SPANNABLE);
                    }


                return true;
            }


        });
    } catch (Exception e) {
        e.printStackTrace();
    }

}
于 2016-09-27T09:41:39.473 に答える