【发布时间】:2016-07-27 14:13:07
【问题描述】:
我正在膨胀一个布局以在屏幕上显示它。
现在我想将该布局部分移出屏幕。我尝试在膨胀的布局上使用.animate().translationX(-500)。它完全按照我想要的样子移出屏幕:
之前:
之后:
但是现在我的问题是布局最初占用的区域不可点击(例如不能在主屏幕之间滑动,只能在蓝色标记区域之外工作)。
我该如何解决这个问题,所以蓝色区域在移动后是可点击的,但布局的剩余区域(红色区域)仍然可以注册点击(例如,如果我想使用 onClickListener 将其移回)?
我想我必须使用windowManager 的updateViewLayout() 函数,但我不知道我应该对参数进行哪些更改。
编辑 1:
这里是代码。翻译由按钮触发:
overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d8ff0000"
android:weightSum="1">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="245dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Lorem ipsum "
android:id="@+id/textView6"
android:layout_marginLeft="10dp" />
<Button
android:layout_width="55dp"
android:layout_height="wrap_content"
android:text="X"
android:id="@+id/button"
android:layout_gravity="center_horizontal|top"
android:layout_alignParentTop="true"
android:layout_toEndOf="@+id/textView6"
android:layout_marginStart="27dp" />
</RelativeLayout>
</LinearLayout>
使布局膨胀的服务:
OverlayService.java
public class FloatingMenu extends Service{
private WindowManager wm;
private LinearLayout ll;
private boolean isPushedToSide = true;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
wm = (WindowManager) getSystemService(WINDOW_SERVICE);
ll = new LinearLayout(this);
LinearLayout.LayoutParams llParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
ll.setBackgroundColor(Color.argb(50, 255, 255, 255));
ll.setLayoutParams(llParameters);
final WindowManager.LayoutParams parameters = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT);
parameters.gravity = Gravity.LEFT | Gravity.TOP;
LayoutInflater li = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
ll = (LinearLayout) li.inflate(R.layout.overlay, null);
final Button b = (Button) ll.findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isPushedToSide) {
ll.animate().translationX(0);
isPushedToSide = false;
}else {
ll.animate().translationX(-450);
isPushedToSide = true;
}
}
});
wm.addView(ll, parameters);
}
}
编辑 2:
在继续我的研究时,我发现.animate().translationX() 只会移动视图呈现的位置,而不是视图本身。这也解释了为什么在使用.animate().translationX() 之后,onclick 事件仍会在与“移动”布局之前相同的位置触发。
现在我需要找到一种结合动画将实际视图移动到所需位置的方法。任何想法如何做到这一点?
编辑 3:
我发现很多有类似问题的帖子,如果我是对的,问题的解决方案是使用ObjectAnimator 而不是.animate().translationX()。
我尝试在我的代码中替换该部分,以便 onClickListener 现在看起来像这样:
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isPushedToSide) {
//ll.animate().translationX(0);
ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start();
isPushedToSide = false;
}else {
//ll.animate().translationX(-450);
ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start();
isPushedToSide = true;
}
}
});
ll 是我膨胀的LinearLayout,包含Lorem ipsum 文本和Button。
同样,动画本身工作正常,但行为方式仍然相同。我仍然需要点击按钮的原始位置才能触发onClickListener,蓝色区域仍然不可点击。
编辑 4:
正在尝试使用.invalidate() 更新实际位置的建议。然而它没有用。我不确定它是否正确使用。
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isPushedToSide) {
//ll.animate().translationX(0);
ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250).start();
ll.invalidate();
isPushedToSide = false;
}else {
//ll.animate().translationX(-450);
ObjectAnimator.ofFloat(ll, "translationX", -450).setDuration(250).start();
ll.invalidate();
isPushedToSide = true;
}
}
});
我还尝试更改LayoutParams 的x 值并调用wm.updateViewLayou(ll, updatedParameters),效果很好。当我将叠加层向右移动 100 像素时,触发 onClickListener 的区域也被向右推 100 像素。问题是我只能在实际屏幕的边界内移动叠加层,而我需要将其移出屏幕。绑定负值,但这也不起作用。
我本质上需要的是抽屉式导航,但高度有限(至少我认为这是我需要的)。我会看看我是否可以让某些东西以这种方式正常工作。
编辑 5:
更正了我的代码,以便在动画完成时调用 .inflate(),但它的行为仍然相同:
ObjectAnimator anim = ObjectAnimator.ofFloat(ll, "translationX", 0).setDuration(250);
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationEnd(Animator animator) {
b.invalidate();
text.invalidate();
frame.invalidate();
ll.invalidate();
}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
});
anim.start();
【问题讨论】:
标签: android android-layout android-animation layout-inflater