我正在尝试创建一个从底部向上滑动的菜单。它从菜单的视图开始,只在屏幕底部可见,然后单击它使其向上滑动。我尝试使用TranslateAnimation
,但是虽然像素移动,但菜单的命中区域与之前的位置相同。所以我认为如果我可以在动画完成后调整菜单的边距,这将完成我想要的。但是,我无法弄清楚如何调整边距。
我尝试创建一个LinearLayout.LayoutMargins
对象,然后设置其边距并将其应用到菜单的视图(LinearLayout
),但这不起作用。
有什么想法吗?
答案 0 :(得分:21)
以下对我有用。首先确定菜单向上(完全可见)或向下(大部分隐藏)的下边距(以逢低计)。
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);
}
瞧!
答案 1 :(得分:3)
我的解决方案是创建两个LinearLayouts,一个处于up状态(设置为消失),另一个处于菜单的down状态。然后,当用户点击按钮向上滑动菜单时,我会调出TranslateAnimation
,显示菜单向上滑动。我在动画上放置了一个监听器,使得up状态可见,当动画结束时,down状态消失。为了“结束”行动,我改变了这一点。
不完全是我原先想象的方式,但它确实有效。
答案 2 :(得分:3)
使用ViewPropertyAnimator
:
if (view.getY() != margin) {
view.animate().y(margin).setDuration(150).start();
}
答案 3 :(得分:2)
我觉得这有点不太常见。基本上,它正在制作你自己的动画师。下面的设置仅用于修改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;
}
}
}
}
答案 4 :(得分:1)
这篇文章帮我搞动画。就我而言,我有一个全屏webview。在某些用户操作中,此Web视图向右滑动,大约70%,并从左侧显示新的Web视图并占用可用空间。最终结果是,新的webview覆盖了70%(x轴)和其余的旧webview。 Arne的解决方案极大地帮助了我,一旦动画完成就设置了旧视图的边距。伪代码:
marginParams.leftMargin = 336; //(70% of 480px)
但是我遇到了一个奇怪的行为,我想我的旧webview(现在只占30%的空间),正在重新格式化其内容,可能会认为它现在被挤进一个较小的空间,而不是表现得好像它只是滑向右边。换句话说,一旦我设置了这个边距,webview的html布局就会改变。再一次,我不知道为什么和我的猜测它认为其父窗口大小已更改。基于这个假设,我又增加了一行代码:
marginParams.rightMargin = -336; //(same amount, but negative margin!)
这就是诀窍,没有重新格式化html内容,我可以同时与两个webview进行交互。
我发布这篇文章是一个很大的感谢Arne的想法,也为我看到的行为和我的假设得到任何输入。我实际上喜欢最终解决方案,具有逻辑意义,但我可能错了。 。 。任何想法和意见将不胜感激。非常感谢你。