UI でフィードバックを表示するために使用するカスタムを作成View
しました (通常は、実行中のアクションに応答して)。がFeedbackView.showText
呼び出されると、View
in を 2 秒間アニメートしてから、アニメートします。これは を使用して行われtranslationY
ます。
高さよりも大きい負のマージンを適用すると、最初FeedbackView.showText
に呼び出されたときに正しくアニメーション化されません。表示されるだけです (または、まったく表示されない場合もあります)。FeedbackView.showText
正しいアニメーションを引き起こすための後続の呼び出し。
以下activity_main.xml
でFeedbackView
は、 のマージン top があり-36dp
、これはその高さよりも大きくなっています (ネゲートされていない場合)。マージントップを変更すると、最初の呼び出し-35dp
でも正しくアニメーション化されます。FeedbackView.showText
なぜこのようなことが起こるのか誰か知っていますか?
Romain Guy は、 と で負のマージンを使用しても問題ないLinearLayout
とRelativeLayout
述べています。私の唯一の推測は、彼らがFrameLayout
s に問題があるということです。
フィードバック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>