0

UI でフィードバックを表示するために使用するカスタムを作成Viewしました (通常は、実行中のアクションに応答して)。がFeedbackView.showText呼び出されると、Viewin を 2 秒間アニメートしてから、アニメートします。これは を使用して行われtranslationYます。

高さよりも大きい負のマージンを適用すると、最初FeedbackView.showTextに呼び出されたときに正しくアニメーション化されません。表示されるだけです (または、まったく表示されない場合もあります)。FeedbackView.showText正しいアニメーションを引き起こすための後続の呼び出し。

以下activity_main.xmlFeedbackViewは、 のマージン top があり-36dp、これはその高さよりも大きくなっています (ネゲートされていない場合)。マージントップを変更すると、最初の呼び出し-35dpでも正しくアニメーション化されます。FeedbackView.showText

なぜこのようなことが起こるのか誰か知っていますか?

Romain Guy は、 と で負のマージンを使用しても問題ないLinearLayoutRelativeLayout述べています。私の唯一の推測は、彼らがFrameLayouts に問題があるということです。

フィードバックView.java

public class FeedbackView extends FrameLayout {
  public static final int DEFAULT_SHOW_DURATION = 2000;

  private AtomicBoolean showing = new AtomicBoolean(false);
  private AtomicBoolean animating = new AtomicBoolean(false);

  private float heightOffset;

  private Runnable animateOutRunnable = new Runnable() {
    @Override
    public void run() {
      animateContainerOut();
    }
  };

  public FeedbackView(Context context) {
    super(context);
    init();
  }

  public FeedbackView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public FeedbackView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  public FeedbackView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init();
  }

  private void init() {
    setAlpha(0);
  }

  public boolean isShowing() {
    return showing.get();
  }

  public void showText(Context context, String text) {
    removeCallbacks(animateOutRunnable);

    heightOffset = getMeasuredHeight();

    removeAllViews();

    final TextView tv = new TextView(context);
    tv.setGravity(Gravity.CENTER);
    tv.setTextColor(Color.WHITE);
    tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
    tv.setText(text);

    addView(tv);

    if(!showing.getAndSet(true)) {
      animateContainerIn();
    }
    else {
      tv.setTranslationY(-getHeight());
      tv.animate().translationY(0).start();
    }

    postDelayed(animateOutRunnable, DEFAULT_SHOW_DURATION);
  }

  private void animateContainerIn() {
    if(animating.getAndSet(true)) {
      animate().cancel();
    }

    ViewPropertyAnimator animator = animate();
    long startDelay = animator.getDuration() / 2;

    animate()
        .alpha(1)
        .setStartDelay(startDelay)
        .start();

    animate()
        .translationY(heightOffset)
        .setStartDelay(0)
        .withEndAction(new Runnable() {
          @Override
          public void run() {
            animating.set(false);
            showing.set(true);
          }
        })
        .start();
  }

  private void animateContainerOut() {
    showing.set(false);

    if(animating.getAndSet(true)) {
      animate().cancel();
    }

    ViewPropertyAnimator animator = animate();
    long duration = animator.getDuration();

    animate()
        .alpha(0)
        .setDuration(duration / 2)
        .start();

    animate()
        .translationY(-heightOffset)
        .setDuration(duration)
        .withEndAction(new Runnable() {
          @Override
          public void run() {
            animating.set(false);
          }
        })
        .start();
  }
}

MainActivity.java

public class MainActivity extends Activity {
  private FeedbackView feedbackView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    feedbackView = (FeedbackView) findViewById(R.id.feedback);

    findViewById(R.id.show_feedback).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        feedbackView.showText(MainActivity.this, "Feedback");
      }
    });
  }
}

activity_main.xml

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

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="70dp"
    android:background="#000"
    android:clickable="true"/>

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <FrameLayout
      android:layout_width="match_parent"
      android:layout_height="90dp"/>

    <FrameLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:clickable="true"
      android:background="#e9e9e9"/>

    <negative.margin.FeedbackView
      android:id="@+id/feedback"
      android:layout_width="match_parent"
      android:layout_height="35dp"
      android:layout_marginTop="-36dp"
      android:background="#20ACE0"/>

  </FrameLayout>

  <Button
    android:id="@+id/show_feedback"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|center"
    android:text="Show Feedback"/>

</LinearLayout>
4

1 に答える 1