Android- LinearLayout 또는 Relativelayout에서 뷰의 Topmargin/Bottommargin/등을 애니메이션
-
19-09-2019 - |
문제
바닥에서 미끄러지는 메뉴를 만들려고합니다. 화면 하단에서 볼 수있는 메뉴보기로 시작한 다음 클릭하면 위로 미끄러집니다. 나는 a를 사용했다 TranslateAnimation
, 그러나 픽셀이 움직이지만 메뉴의 적중 영역은 이전과 동일한 위치에 있습니다. 애니메이션이 완료된 후 메뉴의 여백을 조정할 수 있다면 이것이 내가 원하는 것을 달성 할 것이라고 생각합니다. 그러나 여백을 조정하는 방법을 알 수 없습니다.
나는 만들려고 노력했다 LinearLayout.LayoutMargins
객체를 한 다음 여백을 설정하고 메뉴의보기에 적용합니다 ( LinearLayout
),하지만 이것은 작동하지 않습니다.
어떤 아이디어?
해결책 2
내 솔루션은 두 개의 선형 레이 아웃을 만드는 것이 었습니다. 하나는 up 상태에 있고 다른 하나는 메뉴의 아래 상태에 있습니다. 그런 다음 사용자가 버튼을 클릭하여 메뉴를 미끄러지면 TranslateAnimation
메뉴가 미끄러 져 올라갑니다. 애니메이션이 완료되면 UP 상태가 보이고 다운 상태가 사라지는 애니메이션에 청취자를 넣었습니다. 나는 "폐쇄"액션을 위해 이것을 뒤집었다.
내가 원래 상상했던 방식이 아니라 효과가 있었지만 효과가있었습니다.
다른 팁
다음은 나를 위해 일했습니다. 먼저 메뉴가 위로 올라가거나 아래로 (대부분 숨겨진)에 대한 하단 마진 (딥)을 결정하십시오.
private static final int BOTTOM_MARGIN_UP = -50; // My menu view is a bit too tall.
private static final int BOTTOM_MARGIN_DOWN = -120;
그런 다음 oncreate ()에서 :
menuLinearLayout = (LinearLayout)findViewById(R.id.menuLinearLayout);
setBottomMargin(menuLinearLayout, BOTTOM_MARGIN_DOWN);
upAnimation = makeAnimation(BOTTOM_MARGIN_DOWN, BOTTOM_MARGIN_UP);
downAnimation = makeAnimation(BOTTOM_MARGIN_UP, BOTTOM_MARGIN_DOWN);
Button toggleMenuButton = (Button)findViewById(R.id.toggleMenuButton);
toggleMenuButton.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View view, MotionEvent motionEvent)
{
if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) return false;
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams)menuLinearLayout.getLayoutParams();
boolean isUp = layoutParams.bottomMargin == dipsToPixels(BOTTOM_MARGIN_UP);
menuLinearLayout.startAnimation(isUp ? downAnimation : upAnimation);
return true;
}
});
그리고 여기 비밀 소스가 온다 ;-)
private TranslateAnimation makeAnimation(final int fromMargin, final int toMargin)
{
TranslateAnimation animation =
new TranslateAnimation(0, 0, 0, dipsToPixels(fromMargin - toMargin));
animation.setDuration(250);
animation.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationEnd(Animation animation)
{
// Cancel the animation to stop the menu from popping back.
menuLinearLayout.clearAnimation();
// Set the new bottom margin.
setBottomMargin(menuLinearLayout, toMargin);
}
public void onAnimationStart(Animation animation) {}
public void onAnimationRepeat(Animation animation) {}
});
return animation;
}
두 가지 유틸리티 기능을 사용합니다.
private void setBottomMargin(View view, int bottomMarginInDips)
{
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams)view.getLayoutParams();
layoutParams.bottomMargin = dipsToPixels(bottomMarginInDips);
view.requestLayout();
}
private int dipsToPixels(int dips)
{
final float scale = getResources().getDisplayMetrics().density;
return (int)(dips * scale + 0.5f);
}
짜잔!
사용 ViewPropertyAnimator
:
if (view.getY() != margin) {
view.animate().y(margin).setDuration(150).start();
}
나는 이것이 약간의 해킹이라고 생각합니다. 기본적으로 자신만의 애니메이터를 만들고 있습니다. 아래는 수정하기위한 설정입니다 topMargin
안에 RelativeLayout
, 그러나 일반화하기가 어렵지는 않습니다.
import java.util.Calendar;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout.LayoutParams;
public class MarginAnimation extends Thread {
final String TAG = "MarginAnimation";
long mStartTime;
long mTotalTime;
Interpolator mI;
int mStartMargin;
int mEndMargin;
View mV;
Activity mA;
public MarginAnimation(Activity a, View v,
int startMargin, int endMargin, int totaltime,
Interpolator i) {
mV = v;
mStartMargin = startMargin;
mEndMargin = endMargin;
mTotalTime = totaltime;
mI = i;
mA = a;
}
@Override
public void run() {
mStartTime = Calendar.getInstance().getTimeInMillis();
while(!this.isInterrupted() &&
Calendar.getInstance().getTimeInMillis() - mStartTime < mTotalTime) {
mA.runOnUiThread(new Runnable() {
@Override
public void run() {
if(MarginAnimation.this.isInterrupted())
return;
long cur_time = Calendar.getInstance().getTimeInMillis();
float perc_done = 1.0f*(cur_time-mStartTime)/mTotalTime;
final int new_margin = (int)(1.0f*(mEndMargin-mStartMargin)*mI.getInterpolation(perc_done)) + mStartMargin;
LayoutParams p = (LayoutParams) mV.getLayoutParams();
Log.v(TAG, String.format("Setting Margin to %d", new_margin));
p.topMargin = new_margin;
mV.setLayoutParams(p);
}
});
try {
Thread.sleep(50);
} catch (InterruptedException e) {
return;
}
}
}
}
이 게시물은 제 애니메이션이 작동하는 데 도움이되었습니다. 제 경우에는 전체 화면 웹 뷰가 있습니다. 일부 사용자 조치 에서이 WebView는 오른쪽으로 미끄러 져 약 70%이며 새로운 WebView가 왼쪽에서 나오고 사용 가능한 공간을 차지합니다. 최종 결과, 새로운 WebView는 70% (x 축)와 오래된 웹 뷰를 포함합니다. Arne의 솔루션은 애니메이션이 완료 되 자마자 오래된 시야에 여백을 설정하면서 저를 엄청나게 도와주었습니다. 의사 코드 :
marginParams.leftMargin = 336; //(70% of 480px)
그러나 나는 이상한 행동에 직면했고, 내 오래된 웹 뷰 (이제 30% 공간만을 차지하고 있음)가 내용물을 재구성하고 있다고 생각합니다. 오른쪽. 다시 말해,이 마진을 설정하자마자 WebView의 HTML 레이아웃이 변경되었습니다. 다시, 나는 왜 그리고 내 이유를 전혀 몰랐다 추측 부모의 창 크기가 바뀌 었다고 생각합니까? 그 가정을 바탕으로 한 줄의 코드를 추가했습니다.
marginParams.rightMargin = -336; //(same amount, but negative margin!)
그리고 그것은 트릭, HTML 컨텐츠의 재구성이 없었으며 두 웹 뷰와 병렬로 상호 작용할 수 있습니다.
나는 이것을 아이디어에 대해 Arne에게 큰 감사로 게시하고, 내가 본 행동과 내 가정에 대한 입력을 얻기 위해 이것을 많이 감사합니다. 나는 실제로 최종 솔루션을 좋아하고 논리적으로 의미가 있지만 잘못되었을 수도 있습니다. . . 모든 생각과 의견은 크게 감사 할 것입니다. 매우 감사합니다.