Je travaille sur un jeu où le joueur peut faire glisser des objets sur l’écran. J'ai une méthode privée qui me permet de simuler un événement de glisser/déposer pour n'importe lequel des éléments que le joueur peut déplacer. Pour le glisser, je laisse en réalité la vue qu’ils ont touchée et je crée une nouvelle ImageView avec le dessin que je peux dessiner, puis en déplaçant ce dessin dans la vue touchée, puis en déplaçant cette vue nouvellement créée sur l’écran suivant leur doigt. Lorsque vous relâchez votre doigt (laissez tomber la vue), j'appelle myLayout.remove(movingImg);
pour le retirer de l'écran. J'ai un problème où si je commence un événement de glisser simulé, puis que je récupère manuellement l'un des autres éléments, un pointeur null apparaît sur l'appel myLayout.remove (), voici la trace de Log:
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): Java.lang.NullPointerException
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:2122)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.drawChild(ViewGroup.Java:2506)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:2123)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.drawChild(ViewGroup.Java:2506)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:2123)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.drawChild(ViewGroup.Java:2506)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:2123)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.drawChild(ViewGroup.Java:2506)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:2123)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.View.draw(View.Java:9032)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.widget.FrameLayout.draw(FrameLayout.Java:419)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at com.Android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.Java:1910)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewRoot.draw(ViewRoot.Java:1608)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewRoot.performTraversals(ViewRoot.Java:1329)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1944)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.os.Handler.dispatchMessage(Handler.Java:99)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.os.Looper.loop(Looper.Java:126)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Android.app.ActivityThread.main(ActivityThread.Java:3997)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Java.lang.reflect.Method.invokeNative(Native Method)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at Java.lang.reflect.Method.invoke(Method.Java:491)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:841)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:599)
04-06 10:37:43.610: ERROR/AndroidRuntime(23203): at dalvik.system.NativeStart.main(Native Method)
La trace ne pointe nulle part dans mon activité. L'exception est levée chaque fois qu'elle tente d'appeler myLayout.remove () sur la vue de déplacement par simulation. J'ai entouré cette ligne avec un try/catch mais cela n'a rien fait. Je sais que c'est la ligne qui me pose problème, car si je la commente, je ne reçois pas d'exception, mais évidemment, mon point de vue n'est jamais supprimé de l'écran. Je construis cette application sur un Motorola xoom, mais je ne suis pas sûr qu'il s'agisse d'un problème spécifique à l'appareil. Est-ce que quelqu'un sait ce qui pourrait se passer ici?
C'est à partir de là que le .removeView () est appelé:
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
Log.i(myTag, "Animation End");
try {
//myLayout.removeView(simulateMovingImg); //This is the line that is throwing a null pointer
simulateMovingImg.setVisibility(View.GONE); //This is how I am currently getting around the issue
params = new LayoutParams(oneImg.getWidth(),oneImg.getHeight()); // While its moving it appears larger than normal
simulateMovingImg.setLayoutParams(params); // so I set it back to the normal size
if(whichTarget == true){
targetImg.setImageDrawable(simulateMovingImg.getDrawable()); //targetImg is one of the 'drop zones' so I set its
// drawable to make it seem like the view was 'dropped' into this zone
}else{
target1Img.setImageDrawable(simulateMovingImg.getDrawable()); // same with target1Img.
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
iAmDone = true;
}
});
C'est à l'intérieur d'un AnimationListener pour l'animation de traduction qui déplace mon ImageView d'où il commence à être "déposé"
Android fera une exception lorsque vous modifiez la hiérarchie des vues dans animationEnd.
Tout ce que vous avez à faire est de reporter votre appel comme suit:
@Override
public void onAnimationEnd(Animation animation) {
new Handler().post(new Runnable() {
public void run() {
myLayout.removeView(simulateMovingImg);
}
});
}
Pouvez-vous essayer ceci, pour vous assurer que simulateMovingImg est présent
if (myLayout.indexOfChild() >= 0)
{
myLayout.removeView(simulateMovingImg);
}
J'ai légèrement modifié une réponse acceptée (cela fonctionne également) pour éviter les gestionnaires.
@Override
public void onAnimationEnd(Animation animation) {
imageView.post(new Runnable() {
@Override
public void run() {
layout.removeView(imageView);
}
});
}
Je suppose que c'est un problème de multi-threading. Il semble que la boucle de rendu Android interne rencontre un pointeur null en raison du fait que vous avez supprimé l'image d'un autre thread. Le cadre de l'interface utilisateur Android est à thread unique et toutes les modifications de l'interface utilisateur doivent avoir lieu dans le fil de l'interface utilisateur. Si tel est le problème que vous rencontrez, vous pouvez simplement déléguer votre appel au thread d'interface utilisateur.
Il y a quelques informations connexes ici: Android threading
J'ai rencontré ce problème après avoir mis à jour l'appcompat-v7. La dernière version stable de la dépendance susmentionnée est la suivante:
compile 'com.Android.support:appcompat-v7:23.2.1'