나는이 LinearLayout
내가 보여이나와 숨기려는 것을 Animation
나는 그것의 가시성을 변경할 때마다 위쪽으로 레이아웃을 못살게 굴지 또는 아래쪽으로.
나는 몇 가지 샘플을 보았지만 그 중 어느 것도 내 요구에 맞지 않습니다.
애니메이션에 대해 두 개의 xml 파일을 만들었지 만의 표시 여부를 변경할 때 시작하는 방법을 모르겠습니다 LinearLayout
.
나는이 LinearLayout
내가 보여이나와 숨기려는 것을 Animation
나는 그것의 가시성을 변경할 때마다 위쪽으로 레이아웃을 못살게 굴지 또는 아래쪽으로.
나는 몇 가지 샘플을 보았지만 그 중 어느 것도 내 요구에 맞지 않습니다.
애니메이션에 대해 두 개의 xml 파일을 만들었지 만의 표시 여부를 변경할 때 시작하는 방법을 모르겠습니다 LinearLayout
.
답변:
Android 3.0 (Honeycomb)에 도입 된 새로운 애니메이션 API를 사용하면 이러한 애니메이션을 만드는 것이 매우 간단합니다.
View
거리만큼 아래로 슬라이딩 :
view.animate().translationY(distance);
나중에 View
다음과 같이 원래 위치로 다시 밀어 넣을 수 있습니다 .
view.animate().translationY(0);
여러 애니메이션을 쉽게 결합 할 수도 있습니다. 다음 애니메이션은 View
높이를 아래로 슬라이드 하여 동시에 페이드 인합니다.
// Prepare the View for the animation
view.setVisibility(View.VISIBLE);
view.setAlpha(0.0f);
// Start the animation
view.animate()
.translationY(view.getHeight())
.alpha(1.0f)
.setListener(null);
그런 다음 View
뒤로 물러서서 원래 위치로 밀어 넣을 수 있습니다 . 또한 애니메이션이 완료되면 뒤로 AnimatorListener
의 가시성을 설정할 수 있도록 설정했습니다 .View
GONE
view.animate()
.translationY(0)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setVisibility(View.GONE);
}
});
View
가시성이 설정되어있을 때 애니메이션으로 무엇을 달성하려고 View.GONE
합니까? 이 외에 아무것도에 대한 가시성을 설정하면 View.VISIBLE
다음은 View
표시되지 않습니다. 나는 당신이 무엇을 요구하는지 이해하지 못합니다. 당신이 당신의 애니메이션을 볼 수 있도록하려면 다음의 가시성 설정하지 마십시오 View
에를 View.GONE
.
onAnimationEnd
는 다중 발생 애니메이션을 위해 매번 청취자 가 호출된다는 것 onAnimationEnd
입니다. 즉 , 뷰가 표시 될 때 호출되어 가시성을 사라짐 등으로 설정합니다.
허용되는 답변을 적용하는 데 어려움을 겪고있었습니다. 좀 더 문맥이 필요했습니다. 이제 알아 냈습니다. 전체 예는 다음과 같습니다.
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button myButton;
View myView;
boolean isUp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = findViewById(R.id.my_view);
myButton = findViewById(R.id.my_button);
// initialize as invisible (could also do in xml)
myView.setVisibility(View.INVISIBLE);
myButton.setText("Slide up");
isUp = false;
}
// slide the view from below itself to the current position
public void slideUp(View view){
view.setVisibility(View.VISIBLE);
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
view.getHeight(), // fromYDelta
0); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
// slide the view from its current position to below itself
public void slideDown(View view){
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
0, // fromYDelta
view.getHeight()); // toYDelta
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
}
public void onSlideViewButtonClick(View view) {
if (isUp) {
slideDown(myView);
myButton.setText("Slide up");
} else {
slideUp(myView);
myButton.setText("Slide down");
}
isUp = !isUp;
}
}
activity_mail.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.slideview.MainActivity">
<Button
android:id="@+id/my_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:onClick="onSlideViewButtonClick"
android:layout_width="150dp"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/my_view"
android:background="#a6e1aa"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="200dp">
</LinearLayout>
</RelativeLayout>
INVISIBLE
.INVISIBLE
. 그래도 화면에서 완전히 애니메이션을 적용하지 않는 경우 알파 애니메이션을 추가하고로 가시성을 설정할 수 있습니다 AnimatorListenerAdapter
..setVisibility(View.INVISIBLE);
기능까지 슬라이드로 작동하지 않습니다 시각적으로 기대했다.
Translate Animation
보기를 이동합니다. 스케일링 자체와 같은 뷰를 애니메이션하려면ScaleAnimation anim = new ScaleAnimation(1, 1, 0, 1)
이제 가시성 변경 애니메이션은 Transition API
지원 (androidx) 패키지에서 사용 가능한 것을 통해 수행되어야 합니다. 슬라이드 전환으로 TransitionManager.beginDelayedTransition 메소드를 호출 한 다음보기의 가시성을 변경하십시오.
import androidx.transition.Slide;
import androidx.transition.Transition;
import androidx.transition.TransitionManager;
private void toggle(boolean show) {
View redLayout = findViewById(R.id.redLayout);
ViewGroup parent = findViewById(R.id.parent);
Transition transition = new Slide(Gravity.BOTTOM);
transition.setDuration(600);
transition.addTarget(R.id.redLayout);
TransitionManager.beginDelayedTransition(parent, transition);
redLayout.setVisibility(show ? View.VISIBLE : View.GONE);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play" />
<LinearLayout
android:id="@+id/redLayout"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#5f00"
android:layout_alignParentBottom="true" />
</RelativeLayout>
다른 기본 및 사용자 정의 전환 예제를 사용 하여이 답변 을 확인하십시오 .
minSdkVersion 21
androidx
패키지 에서 제공 됩니다. 21 api 이전에는 잘 작동합니다.
가장 쉬운 솔루션 : android:animateLayoutChanges="true"
뷰를 유지하는 컨테이너에 설정 하십시오.
일부 컨텍스트에 배치하려면 다음과 같은 레이아웃이있는 경우이 컨테이너의보기에 대한 모든 가시성 변경 사항이 자동으로 애니메이션됩니다.
<LinearLayout android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
>
<Views_which_change_visibility>
</LinearLayout>
레이아웃 변경 애니메이션 적용-Android 개발자 에서 이에 대한 자세한 내용을 확인할 수 있습니다
의 하위 클래스를 새로 만들고 재정 의하여을 ( 를) 재정 의하여 변경 내용을 Animation
표시 할 때 올바른 시작을 시작할 수 있습니다 . 다음과 같은 것을 고려하십시오.LinearLayout
LinearLayout
setVisibility()
Animations
public class SimpleViewAnimator extends LinearLayout
{
private Animation inAnimation;
private Animation outAnimation;
public SimpleViewAnimator(Context context)
{
super(context);
}
public void setInAnimation(Animation inAnimation)
{
this.inAnimation = inAnimation;
}
public void setOutAnimation(Animation outAnimation)
{
this.outAnimation = outAnimation;
}
@Override
public void setVisibility(int visibility)
{
if (getVisibility() != visibility)
{
if (visibility == VISIBLE)
{
if (inAnimation != null) startAnimation(inAnimation);
}
else if ((visibility == INVISIBLE) || (visibility == GONE))
{
if (outAnimation != null) startAnimation(outAnimation);
}
}
super.setVisibility(visibility);
}
}
View
것이 아닌 자체 애니메이션을 책임지게합니다 . View
앱의 다른 부분 에서 다르게 애니메이션을 적용한다고 가정 해보십시오. 그럼 어떻게합니까? 가시성을 자동으로 애니메이션하지 않으려면 플래그를 추가 하시겠습니까? 애니메이션을 제거하기 위해 서브 클래 싱 View
및 재정의 setVisibility()
? 아니면 setVisibility()
다른 애니메이션으로 더 나쁜 구현 을 하시겠습니까? 거기에서 더 추악 해지고 더 추해집니다. 이 "솔루션"을 사용하지 마십시오.
코 틀린
를 기반으로 Suragch 의 대답 , 여기보기 확장을 사용하여 우아한 방법입니다 :
fun View.slideUp(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun View.slideDown(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
그런 다음 어디에서 사용 myView.slideUp()
하든myView.slideDown()
if (filter_section.getVisibility() == View.GONE) {
filter_section.animate()
.translationY(filter_section.getHeight()).alpha(1.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
filter_section.setVisibility(View.VISIBLE);
filter_section.setAlpha(0.0f);
}
});
} else {
filter_section.animate()
.translationY(0).alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
filter_section.setVisibility(View.GONE);
}
});
}
setAlpha
?
Android 앱에서 벨로우즈 코드를 사용하여 모든보기 또는 레이아웃을 위아래로 슬라이드 할 수 있습니다
boolean isClicked=false;
LinearLayout mLayoutTab = (LinearLayout)findViewById(R.id.linearlayout);
if(isClicked){
isClicked = false;
mLayoutTab.animate()
.translationYBy(120)
.translationY(0)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}else{
isClicked = true;
mLayoutTab.animate()
.translationYBy(0)
.translationY(120)
.setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
이 수업을 사용하십시오 :
public class ExpandCollapseExtention {
public static void expand(View view) {
view.setVisibility(View.VISIBLE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(widthSpec, heightSpec);
ValueAnimator mAnimator = slideAnimator(view, 0, view.getMeasuredHeight());
mAnimator.start();
}
public static void collapse(final View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(view, finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
mAnimator.start();
}
private static ValueAnimator slideAnimator(final View v, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
layoutParams.height = value;
v.setLayoutParams(layoutParams);
}
});
return animator;
}
}
ObjectAnimator 사용
private fun slideDown(view: View) {
val height = view.height
ObjectAnimator.ofFloat(view, "translationY", 0.toFloat(), height.toFloat()).apply {
duration = 1000
start()
}
}
private fun slideUp(view: View) {
val height = view.height
ObjectAnimator.ofFloat(view, "translationY", height.toFloat(),0.toFloat()).apply {
duration = 1000
start()
}
}
0.toFloat()
또한 단지가 될 수0f
뷰 높이가 여전히 zero
너무나 코너 케이스가 있었다 ...
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.view.View;
public final class AnimationUtils {
public static void slideDown(final View view) {
view.animate()
.translationY(view.getHeight())
.alpha(0.f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// superfluous restoration
view.setVisibility(View.GONE);
view.setAlpha(1.f);
view.setTranslationY(0.f);
}
});
}
public static void slideUp(final View view) {
view.setVisibility(View.VISIBLE);
view.setAlpha(0.f);
if (view.getHeight() > 0) {
slideUpNow(view);
} else {
// wait till height is measured
view.post(new Runnable() {
@Override
public void run() {
slideUpNow(view);
}
});
}
}
private static void slideUpNow(final View view) {
view.setTranslationY(view.getHeight());
view.animate()
.translationY(0)
.alpha(1.f)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setVisibility(View.VISIBLE);
view.setAlpha(1.f);
}
});
}
}
여기 내 해결책이 있습니다. 뷰에 대한 참조를 얻고이 메소드를 호출하십시오.
public static void animateViewFromBottomToTop(final View view){
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
final int TRANSLATION_Y = view.getHeight();
view.setTranslationY(TRANSLATION_Y);
view.setVisibility(View.GONE);
view.animate()
.translationYBy(-TRANSLATION_Y)
.setDuration(500)
.setStartDelay(200)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(final Animator animation) {
view.setVisibility(View.VISIBLE);
}
})
.start();
}
});
}
다른 것을 할 필요가 없습니다 =)
코 틀린에서 수 라흐의 대답. 이것은 나를 위해 일했습니다.
class MainActivity : AppCompatActivity() {
var isUp: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myView: View = findViewById(R.id.my_view)
var myButton: Button = findViewById(R.id.my_button)
//Initialize as invisible
myView.visibility = View.INVISIBLE
myButton.setText("Slide up")
isUp = false
}
fun View.slideUp(duration: Int = 500){
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, this.height.toFloat(), 0f)
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun View.slideDown(duration: Int = 500) {
visibility = View.VISIBLE
val animate = TranslateAnimation(0f, 0f, 0f, this.height.toFloat())
animate.duration = duration.toLong()
animate.fillAfter = true
this.startAnimation(animate)
}
fun onSlideViewButtonClick(view: View){
if(isUp){
my_view.slideDown()
my_button.setText("Slide Up")
}
else{
my_view.slideUp()
my_button.setText("Slide Down")
}
isUp = !isUp
}
}
간단한 세 줄의 코드를 사용하여 애니메이션을 표시 할 수 있습니다 ...
//getting the hiding view by animation
mbinding.butn.setOnClickListener {
val SlideOutLeft = AnimationUtils.loadAnimation(this, R.anim.slide_out_left)
simplelayout.visibility = View.INVISIBLE
simplelayout.startAnimation(SlideOutLeft)
val SlideInRight = AnimationUtils.loadAnimation(applicationContext, R.anim.slide_in_right)
animation1.visibility = View.VISIBLE
animation1.startAnimation(SlideInRight)
}
//again unhide the view animation
mbinding.buttn.setOnClickListener {
val SlideInLeft=AnimationUtils.loadAnimation(this,R.anim.slide_in_left)
//set the layout
simplelayout.visibility=View.VISIBLE
simplelayout.startAnimation(SlideInLeft)
val SlideOutRight=AnimationUtils.loadAnimation(this,R.anim.slide_out_right)
animation1.visibility=View.INVISIBLE
animation1.startAnimation(SlideOutRight)
}
Kotlin 확장을 사용하면 다음을 사용할 수 있습니다.
enum class SlideDirection{
UP,
DOWN,
LEFT,
RIGHT
}
enum class SlideType{
SHOW,
HIDE
}
fun View.slideAnimation(direction: SlideDirection, type: SlideType, duration: Long = 250){
val fromX: Float
val toX: Float
val fromY: Float
val toY: Float
val array = IntArray(2)
getLocationInWindow(array)
if((type == SlideType.HIDE && (direction == SlideDirection.RIGHT || direction == SlideDirection.DOWN)) ||
(type == SlideType.SHOW && (direction == SlideDirection.LEFT || direction == SlideDirection.UP)) ){
val displayMetrics = DisplayMetrics()
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.defaultDisplay.getMetrics(displayMetrics)
val deviceWidth = displayMetrics.widthPixels
val deviceHeight = displayMetrics.heightPixels
array[0] = deviceWidth
array[1] = deviceHeight
}
when (direction) {
SlideDirection.UP -> {
fromX = 0f
toX = 0f
fromY = if(type == SlideType.HIDE) 0f else (array[1] + height).toFloat()
toY = if(type == SlideType.HIDE) -1f * (array[1] + height) else 0f
}
SlideDirection.DOWN -> {
fromX = 0f
toX = 0f
fromY = if(type == SlideType.HIDE) 0f else -1f * (array[1] + height)
toY = if(type == SlideType.HIDE) 1f * (array[1] + height) else 0f
}
SlideDirection.LEFT -> {
fromX = if(type == SlideType.HIDE) 0f else 1f * (array[0] + width)
toX = if(type == SlideType.HIDE) -1f * (array[0] + width) else 0f
fromY = 0f
toY = 0f
}
SlideDirection.RIGHT -> {
fromX = if(type == SlideType.HIDE) 0f else -1f * (array[0] + width)
toX = if(type == SlideType.HIDE) 1f * (array[0] + width) else 0f
fromY = 0f
toY = 0f
}
}
val animate = TranslateAnimation(
fromX,
toX,
fromY,
toY
)
animate.duration = duration
animate.setAnimationListener(object: Animation.AnimationListener{
override fun onAnimationRepeat(animation: Animation?) {
}
override fun onAnimationEnd(animation: Animation?) {
if(type == SlideType.HIDE){
visibility = View.INVISIBLE
}
}
override fun onAnimationStart(animation: Animation?) {
visibility = View.VISIBLE
}
})
startAnimation(animate)
}
확장의 예 :
view.slideAnimation(SlideDirection.UP, SlideType.HIDE)//to make it disappear through top of the screen
view.slideAnimation(SlideDirection.DOWN, SlideType.SHOW)//to make it reappear from top of the screen
view.slideAnimation(SlideDirection.DOWN, SlideType.HIDE)//to make it disappear through bottom of the screen
view.slideAnimation(SlideDirection.UP, SlideType.SHOW)//to make it reappear from bottom of the screen