Android добавляет простые анимации во время установки видимости (view.Gone)
Я разработал простой макет. Я закончил дизайн без анимации, но теперь я хочу добавить анимацию, когда в текстовом клике происходит событие, и я не знаю, как его использовать. Мой дизайн XML выглядит хорошо или нет? Мы ценим любые предложения.
Мой XML
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:longClickable="false"
android:orientation="vertical"
android:weightSum="16" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#00DDA0"
android:layout_weight="3" >
</LinearLayout>
<TextView
android:id="@+id/Information1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:text="Child Information"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout1"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="8.5"
android:background="#BBBBBB"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
<TextView
android:id="@+id/Information2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Parent Information"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout2"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#BBBBBB"
android:layout_weight="8.5" >
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
<TextView
android:id="@+id/Information3"
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Siblings"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout3"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#BBBBBB"
android:layout_weight="8.5" >
<TextView
android:id="@+id/textView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
<TextView
android:id="@+id/Information4"
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Teacher Information"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout4"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#BBBBBB"
android:layout_weight="8.5" >
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
<TextView
android:id="@+id/Information5"
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Grade Information"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout5"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#BBBBBB"
android:layout_weight="8.5" >
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView" />
</LinearLayout>
<TextView
android:id="@+id/Information6"
android:layout_width="match_parent"
android:layout_height="0dp"
android:text="Health Information"
android:background="#0390BE"
android:layout_weight="0.75"
android:textColor="#FFFFFF"
android:layout_gravity="center|fill_horizontal"/>
<LinearLayout
android:id="@+id/layout6"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#BBBBBB"
android:layout_weight="8.5" >
<TextView
android:id="@+id/textView5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="TextView"
android:layout_weight="8.5" />
</LinearLayout>
</LinearLayout>
Моя ява
public class Certify_Info extends Activity {
private static TextView tv2,tv3,tv5,tv6,tv4,tv1;
private static LinearLayout l1,l2,l3,l4,l5,l6;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_certify__info);
tv1=(TextView) findViewById(R.id.Information1);
tv2=(TextView) findViewById(R.id.Information2);
tv3=(TextView) findViewById(R.id.Information3);
tv4=(TextView) findViewById(R.id.Information4);
tv5=(TextView) findViewById(R.id.Information5);
tv6=(TextView) findViewById(R.id.Information6);
l1=(LinearLayout) findViewById(R.id.layout1);
l2=(LinearLayout) findViewById(R.id.layout2);
l3=(LinearLayout) findViewById(R.id.layout3);
l4=(LinearLayout) findViewById(R.id.layout4);
l5=(LinearLayout) findViewById(R.id.layout5);
l6=(LinearLayout) findViewById(R.id.layout6);
l2.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
tv1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l2.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
l1.setVisibility(View.VISIBLE);
}
});
tv2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l1.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
l2.setVisibility(View.VISIBLE);
}
});
tv3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l1.setVisibility(View.GONE);
l2.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
l3.setVisibility(View.VISIBLE);
}
});
tv4.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l1.setVisibility(View.GONE);
l2.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
l4.setVisibility(View.VISIBLE);
}
});
tv5.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l1.setVisibility(View.GONE);
l2.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l6.setVisibility(View.GONE);
l5.setVisibility(View.VISIBLE);
}
});
tv6.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
l1.setVisibility(View.GONE);
l2.setVisibility(View.GONE);
l3.setVisibility(View.GONE);
l4.setVisibility(View.GONE);
l5.setVisibility(View.GONE);
l6.setVisibility(View.VISIBLE);
}
});
}
}
10 ответов
Вы можете сделать две вещи, чтобы добавить анимацию, во-первых, вы можете позволить Android анимировать изменения макета для вас. Таким образом, каждый раз, когда вы изменяете что-то в макете, например, изменяете видимость или положение вида, android автоматически создает анимацию затухания / перехода. Чтобы использовать этот набор
android:animateLayoutChanges="true"
на корневом узле в вашем макете.
Второй вариант - добавить анимацию вручную. Для этого я предлагаю вам использовать новый API анимации, представленный в Android 3.0 (Honeycomb). Я могу привести несколько примеров:
Это затухает View
:
view.animate().alpha(0.0f);
Это возвращает его обратно в:
view.animate().alpha(1.0f);
Это движется View
вниз по высоте:
view.animate().translationY(view.getHeight());
Это возвращает View
в исходное положение после перемещения в другое место:
view.animate().translationY(0);
Вы также можете использовать setDuration()
установить продолжительность анимации. Например, это затухает View
в течение 2 секунд:
view.animate().alpha(0.0f).setDuration(2000);
И вы можете комбинировать столько анимаций, сколько захотите, например, это затухает View
и одновременно перемещает его на 0,3 секунды:
view.animate()
.translationY(view.getHeight())
.alpha(0.0f)
.setDuration(300);
И вы также можете назначить слушателя анимации и реагировать на все виды событий. Например, когда начинается анимация, когда она заканчивается или повторяется и т. Д. Используя абстрактный класс AnimatorListenerAdapter
вам не нужно реализовывать все обратные вызовы AnimatorListener
сразу, но только те, которые вам нужны. Это делает код более читабельным. Например, следующий код затухает View
перемещает его на высоту в течение периода 0,3 секунды (300 миллисекунд), а когда анимация завершена, ее видимость устанавливается на View.GONE
,
view.animate()
.translationY(view.getHeight())
.alpha(0.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
}
});
Самый простой способ оживить Visibility
изменения это использование Transition API
который доступен в пакете поддержки (androidx). Просто позвони TransitionManager.beginDelayedTransition
метод затем изменить видимость представления. Есть несколько переходов по умолчанию, таких как Fade
, Slide
,
private void toggle() {
Transition transition = new Fade();
transition.setDuration(600);
transition.addTarget(R.id.image);
TransitionManager.beginDelayedTransition(parent, transition);
image.setVisibility(show ? View.VISIBLE : View.GONE);
}
куда parent
родитель ViewGroup
анимированного просмотра. Результат:
Вот результат с Slide
переход:
Transition transition = new Slide(Gravity.BOTTOM);
Легко написать собственный переход, если вам нужно что-то другое. Вот пример с CircularRevealTransition
который я написал в другом ответе. Он показывает и скрывает вид с помощью анимации CircularReveal.
Transition transition = new CircularRevealTransition();
android:animateLayoutChanges="true"
опция делает то же самое, она просто использует AutoTransition в качестве перехода.
Попробуйте добавить эту строку в родительский макет axml
android:animateLayoutChanges="true"
Пожалуйста, проверьте эту ссылку. Который позволит анимации, такие как L2R, R2L, T2B, B2T анимации.
Этот код показывает анимацию слева направо
TranslateAnimation animate = new TranslateAnimation(0,view.getWidth(),0,0);
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
view.setVisibility(View.GONE);
если вы хотите сделать это из R2L, используйте
TranslateAnimation animate = new TranslateAnimation(0,-view.getWidth(),0,0);
сверху вниз, как
TranslateAnimation animate = new TranslateAnimation(0,0,0,view.getHeight());
и наоборот...
Основываясь на ответе @ashakirov, вот мое расширение для отображения / скрытия просмотра с анимацией затухания
fun View.fadeVisibility(visibility: Int, duration: Long = 400) {
val transition: Transition = Fade()
transition.duration = duration
transition.addTarget(this)
TransitionManager.beginDelayedTransition(this.parent as ViewGroup, transition)
this.visibility = visibility
}
Пример использования
view.fadeVisibility(View.VISIBLE)
view.fadeVisibility(View.GONE, 2000)
Я смог показать / скрыть меню следующим образом:
MenuView.java (расширяет FrameLayout)
private final int ANIMATION_DURATION = 500;
public void showMenu()
{
setVisibility(View.VISIBLE);
animate()
.alpha(1f)
.setDuration(ANIMATION_DURATION)
.setListener(null);
}
private void hideMenu()
{
animate()
.alpha(0f)
.setDuration(ANIMATION_DURATION)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(View.GONE);
}
});
}
Основываясь на ответе @Xaver Kapeller, я нашел способ создания анимации прокрутки при появлении на экране новых видов (а также анимации, чтобы скрыть их).
Это выходит из этого состояния:
- кнопка
- Последняя кнопка
в
- кнопка
- Кнопка 1
- Кнопка 2
- Кнопка 3
- Кнопка 4
- Последняя кнопка
и наоборот.
Таким образом, когда пользователь нажимает первую кнопку, элементы "Кнопка 1", "Кнопка 2", "Кнопка 3" и "Кнопка 4" будут отображаться с использованием анимации затухания, а элемент "Последняя кнопка" будет перемещаться вниз до конца. Высота макета также изменится, что позволит правильно использовать вид прокрутки.
Это код для отображения элементов с анимацией:
private void showElements() {
// Precondition
if (areElementsVisible()) {
Log.w(TAG, "The view is already visible. Nothing to do here");
return;
}
// Animate the hidden linear layout as visible and set
// the alpha as 0.0. Otherwise the animation won't be shown
mHiddenLinearLayout.setVisibility(View.VISIBLE);
mHiddenLinearLayout.setAlpha(0.0f);
mHiddenLinearLayout
.animate()
.setDuration(ANIMATION_TRANSITION_TIME)
.alpha(1.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
updateShowElementsButton();
mHiddenLinearLayout.animate().setListener(null);
}
})
;
mLastButton
.animate()
.setDuration(ANIMATION_TRANSITION_TIME)
.translationY(mHiddenLinearLayoutHeight);
// Update the high of all the elements relativeLayout
LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();
// TODO: Add vertical margins
layoutParams.height = mLastButton.getHeight() + mHiddenLinearLayoutHeight;
}
и это код, чтобы скрыть элементы анимации:
private void hideElements() {
// Precondition
if (!areElementsVisible()) {
Log.w(TAG, "The view is already non-visible. Nothing to do here");
return;
}
// Animate the hidden linear layout as visible and set
mHiddenLinearLayout
.animate()
.setDuration(ANIMATION_TRANSITION_TIME)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.v(TAG, "Animation ended. Set the view as gone");
super.onAnimationEnd(animation);
mHiddenLinearLayout.setVisibility(View.GONE);
// Hack: Remove the listener. So it won't be executed when
// any other animation on this view is executed
mHiddenLinearLayout.animate().setListener(null);
updateShowElementsButton();
}
})
;
mLastButton
.animate()
.setDuration(ANIMATION_TRANSITION_TIME)
.translationY(0);
// Update the high of all the elements relativeLayout
LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();
// TODO: Add vertical margins
layoutParams.height = mLastButton.getHeight();
}
Обратите внимание, что существует простой способ взломать метод, чтобы скрыть анимацию. На слушателе анимации mHiddenLinearLayout мне пришлось удалить самого слушателя, используя:
mHiddenLinearLayout.animate().setListener(null);
Это связано с тем, что как только слушатель анимации присоединяется к представлению, в следующий раз, когда в этом представлении выполняется любая анимация, слушатель также будет выполняться. Это может быть ошибка в слушателе анимации.
Исходный код проекта находится на GitHub: https://github.com/jiahaoliuliu/ViewsAnimated
Удачного кодирования!
Обновление: для любого слушателя, прикрепленного к представлениям, его следует удалить после окончания анимации. Это делается с помощью
view.animate().setListener(null);
Расширение моего решения
fun View.slideVisibility(visibility: Boolean, durationTime: Long = 300) {
val transition = Slide(Gravity.BOTTOM)
transition.apply {
duration = durationTime
addTarget(this@slideVisibility)
}
TransitionManager.beginDelayedTransition(this.parent as ViewGroup, transition)
this.isVisible = visibility
}
Использовать:
textView.slideVisibility(true)
Найдите приведенный ниже код, чтобы сделать видимым представление в Circuler, если вы отправите true, оно станет невидимым / исчезнувшим. Если вы отправите false, он станет видимым. anyView - это представление, которое вы собираетесь отображать / скрывать, это может быть любое представление (макеты, кнопки и т. д.)
private fun toggle(flag: Boolean, anyView: View) {
if (flag) {
val cx = anyView.width / 2
val cy = anyView.height / 2
val initialRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat()
val anim = ViewAnimationUtils.createCircularReveal(anyView, cx, cy, initialRadius, 0f)
anim.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
anyView.visibility = View.INVISIBLE
}
})
anim.start()
} else {
val cx = anyView.width / 2
val cy = anyView.height / 2
val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat()
val anim = ViewAnimationUtils.createCircularReveal(anyView, cx, cy, 0f, finalRadius)
anyView.visibility = View.VISIBLE
anim.start()
}
}
другая версия
fun View.fadeIn(
offset: Long = 0L,
duration: Long = 200L,
onStart: (() -> Unit)? = null,
onFinish: (() -> Unit)? = null
) {
if (!isAttachedToWindow) {
onStart?.invoke()
visible()
onFinish?.invoke()
return
}
val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in)
anim.startOffset = offset
anim.duration = duration
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {}
override fun onAnimationEnd(animation: Animation?) = onFinish?.invoke() ?: Unit
override fun onAnimationStart(animation: Animation?) {
visible()
onStart?.invoke()
}
})
startAnimation(anim)
}
fun View.fadeOut(
offset: Long = 0L,
duration: Long = 200L,
onStart: (() -> Unit)? = null,
onFinish: (() -> Unit)? = null
) {
if (!isAttachedToWindow) {
onStart?.invoke()
invisible()
onFinish?.invoke()
return
}
val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out)
anim.startOffset = offset
anim.duration = duration
anim.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(animation: Animation?) {}
override fun onAnimationEnd(animation: Animation?) {
invisible()
onFinish?.invoke()
}
override fun onAnimationStart(animation: Animation?) {
onStart?.invoke()
}
})
startAnimation(anim)
}