Java 无法在分离视图上启动此动画制作器!显示效果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26819429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot start this animator on a detached view! reveal effect
提问by End.Game
I'm trying to create the reveal effect in my application but without success. What i want is reveal a cardview when i open a fragment. What i tried so far is:
我正在尝试在我的应用程序中创建显示效果,但没有成功。我想要的是当我打开一个片段时显示一个卡片视图。到目前为止我尝试过的是:
private void toggleInformationView(View view) {
infoContainer = view.findViewById(R.id.contact_card);
int cx = (view.getLeft() + view.getRight()) / 2;
int cy = (view.getTop() + view.getBottom()) / 2;
float radius = Math.max(infoContainer.getWidth(), infoContainer.getHeight()) * 2.0f;
if (infoContainer.getVisibility() == View.INVISIBLE) {
infoContainer.setVisibility(View.VISIBLE);
ViewAnimationUtils.createCircularReveal(infoContainer, cx, cy, 0, radius).start();
} else {
Animator reveal = ViewAnimationUtils.createCircularReveal(
infoContainer, cx, cy, radius, 0);
reveal.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
infoContainer.setVisibility(View.INVISIBLE);
}
});
reveal.start();
}
}
and in the onCreateView
i started the method:
在onCreateView
我开始的方法中:
toggleInformationView(view);
this is the cardview:
这是卡片视图:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:id="@+id/contact_card"
android:visibility="invisible"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:elevation="4dp"
android:foreground="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:padding="10dp"
card_view:cardCornerRadius="2dp" >
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/bg_contact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_weight="0"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="@drawable/banner" />
</LinearLayout>
</android.support.v7.widget.CardView>
and the logcat:
和 logcat:
11-08 17:25:48.541: E/AndroidRuntime(26925): java.lang.IllegalStateException: Cannot start this animator on a detached view!
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.view.RenderNode.addAnimator(RenderNode.java:817)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.java:277)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.view.RenderNodeAnimator.setTarget(RenderNodeAnimator.java:261)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.animation.RevealAnimator.<init>(RevealAnimator.java:37)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.view.ViewAnimationUtils.createCircularReveal(ViewAnimationUtils.java:48)
11-08 17:25:48.541: E/AndroidRuntime(26925): at com.as.asapp.TFragment.toggleInformationView(TFragment.java:64)
11-08 17:25:48.541: E/AndroidRuntime(26925): at com.as.asapp.TFragmentshowInformation(TFragment.java:52)
11-08 17:25:48.541: E/AndroidRuntime(26925): at com.as.asapp.TFragment.onCreateView(TFragment.java:37)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.Fragment.performCreateView(Fragment.java:1786)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.support.v4.app.FragmentManagerImpl.run(FragmentManager.java:454)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.os.Handler.handleCallback(Handler.java:739)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.os.Handler.dispatchMessage(Handler.java:95)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.os.Looper.loop(Looper.java:135)
11-08 17:25:48.541: E/AndroidRuntime(26925): at android.app.ActivityThread.main(ActivityThread.java:5221)
11-08 17:25:48.541: E/AndroidRuntime(26925): at java.lang.reflect.Method.invoke(Native Method)
11-08 17:25:48.541: E/AndroidRuntime(26925): at java.lang.reflect.Method.invoke(Method.java:372)
11-08 17:25:48.541: E/AndroidRuntime(26925): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
11-08 17:25:48.541: E/AndroidRuntime(26925): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Checking, seems that getWidth()
and getHeight()
returns 0. But i don't know if it's the real problem. Thanks
检查,似乎getWidth()
并getHeight()
返回 0。但我不知道这是否是真正的问题。谢谢
采纳答案by Fernando Gallego
This is how I solved it, I added a onLayoutChange listener to the view in onCreateView callback, so whenever it is attached to the view and ready to draw, it makes the reveal
这就是我解决它的方法,我在 onCreateView 回调中向视图添加了一个 onLayoutChange 侦听器,因此每当它附加到视图并准备绘制时,它都会显示
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_map_list, container, false);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
v.removeOnLayoutChangeListener(this);
toggleInformationView(view);
}
});
}
return view;
}
回答by Fernando Gallego
Try to call it on the onViewCreated
method
尝试在onViewCreated
方法上调用它
回答by Ziv Kesten
How about simply placing the method in the onViewCreated() method:
简单地将方法放在 onViewCreated() 方法中如何:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
toggleInformationView(view);
}
it works
有用
回答by BennyKok
You can use runnable to do the anim . The runnable will run after the view's creation .
您可以使用 runnable 来执行 anim 。runnable 将在视图创建后运行。
view.post(new Runnable() {
@Override
public void run() {
//create your anim here
}
});
回答by Hitesh Sahu
I was using custom View so I used isAttachedToWindow()
method to check if view is attached and avoid doing reveal while view is not attached.
我正在使用自定义视图,因此我使用isAttachedToWindow()
方法来检查视图是否已附加,并避免在未附加视图时进行显示。
回答by Alexander
Small addition to Hitesh'sanswer. It's better to use https://developer.android.com/reference/android/support/v4/view/ViewCompat.html#isAttachedToWindow(android.view.View)
Hitesh答案的小补充。最好使用 https://developer.android.com/reference/android/support/v4/view/ViewCompat.html#isAttachedToWindow(android.view.View)
android.support.v4.view.ViewCompat
boolean isAttachedToWindow (View view)
Example:
例子:
LinearLayout rootView = null;
rootView = (LinearLayout) findViewById(R.id.rootView);
boolean isAttachedToWindow = ViewCompat.isAttachedToWindow(rootView);
回答by josedlujan
Use a ViewTreeObserver.
使用 ViewTreeObserver。
ViewTreeObserver viewTreeObserver = rootLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
revealActivity(revealX, revealY);
rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
回答by Sohaib Aslam
ah !!!, so finally here is the solution for this error. Actually, the problem is that we are assigning a view to animation with its height and width, and suddenly we didn't notice that there may be a case, that view won't load properly that time when we are assigning it to animation. So for that, we have to wait until view properly loads.
啊!!!,所以最后这里是这个错误的解决方案。实际上,问题在于我们正在为具有高度和宽度的动画分配视图,突然我们没有注意到可能存在这种情况,即当我们将其分配给动画时,该视图将无法正确加载。所以为此,我们必须等到视图正确加载。
LayoutInflater inflater = this.getLayoutInflater();
View rowView = inflater.inflate( R.layout.fileselecttype,null, true );
rowView or [Your View]
[Your View].post(new Runnable() {
@Override
public void run() {
//Do your animation work here.
}
});
回答by Rehan Sarwar
Check your Layout is attached to window or not by using rootLayout.isAttachedToWindow()
method.
使用rootLayout.isAttachedToWindow()
方法检查您的布局是否附加到窗口。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (rootLayout!= null) {
if(rootLayout.isAttachedToWindow()) {
ViewTreeObserver viewTreeObserver = drawerLayout.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
startRevealAnimation(rootLayout);
rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
}
}
}
回答by Juan Mendez
simplified outside of the scope of the question
超出问题范围的简化
private void startAnimation(@NonNull final View view, @NonNull final Runnable onAttachedToWindow) {
if (view.isAttachedToWindow()) {
onAttachedToWindow.run();
} else {
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
onAttachedToWindow.run();
view.removeOnAttachStateChangeListener(this)
}
@Override
public void onViewDetachedFromWindow(View view) {
}
});
}
}
call startAnimation for one or many animations in mind
为一个或多个动画调用 startAnimation
startAnimation(view, new Runnable() {
@Override
public void run() {
//the code inside toggleInformationView(view)
}
});