2015-10-15 2 views
1

J'écris une application qui va dessiner une bulle sur Canvas. J'ai MainActivity avec sa disposition en tant que simple LinearLayout que j'utilise comme support pour fragment. Mon fragment n'a pas mise en page de xml que je dessine sur la toile, donc je mis sa disposition par programme comme celui-ci:Fragment de retenue

public class BubbleFragment extends Fragment { 

    Bubble bubble; 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 

     //retain fragment 
     setRetainInstance(true); 

     //bubble = new Bubble(getActivity()); //THIS WILL CRASH APP, MOVE TO onCreateView instetad 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.MATCH_PARENT, 
       ViewGroup.LayoutParams.MATCH_PARENT, 
       100); 
     LinearLayout ll = new LinearLayout(getActivity()); 
     ll.setOrientation(LinearLayout.VERTICAL); 

     // instantiate my class that does drawing on Canvas 
     bubble = new Bubble(getActivity()); 
     bubble.setLayoutParams(lp); 
     bubble.setBackgroundColor(Color.BLUE); 
     ll.addView(bubble); //if you create bubble in onCreate() this will crash. Create bubble in onCreateView 

     return ll; 
    } 
} 

Alors, quand je commence mon application, je me attends à bulle pour montrer au milieu de l'écran et déplacez-vous lentement vers le bas. Comme j'utilise setRetainInstance (true) ci-dessus, je m'attends à ce que lorsque je fais pivoter mon écran, la bulle continue là où elle s'était arrêtée avant la rotation. Cependant, il est redessiné à son emplacement initial (au milieu de l'écran).

Je voudrais continuer à dessiner à partir de la position où il était avant que l'orientation de l'écran ne change, pas depuis le début.

Voici mon code à bulles:

public class Bubble extends View { 

    private static final boolean BUBBLING = true; //thread is running to draw 

    private Paint paint; 
    private ShapeDrawable bubble; 

    // coordiantes, radius etc 
    private int x; 
    private int y; 
    private int dx; 
    private int dy; 
    private int r; 
    private int w = 400; 
    private int h = 400; 

    //handler to invalidate (force redraw on main GUI thread from this thread) 
    private Handler handler = new Handler(); 

    public Bubble(Context context) { 
     super(context); 

     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     Display display = wm.getDefaultDisplay(); 
     Point size = new Point(); 
     display.getSize(size); 
     w = size.x; 
     h = size.y; 

     x = w/2; 
     y = h/2; 
     r = 60; 
     dx = 1; 
     dy = 1; 

     bubble = new ShapeDrawable(new OvalShape()); 
     bubble.getPaint().setColor(Color.RED); 
     bubble.setBounds(0, 0, r, r); 

     paint = new Paint(); 
     paint.setAntiAlias(true); 
     paint.setStrokeWidth(10); 
    } 

    @Override 
    protected void onSizeChanged (int w, int h, int oldw, int oldh){ 
     //set bubble parameters (center, size, etc) 

     startAnimation(); 
    } 

    public void startAnimation(){ 
     new Thread(new Runnable() { 
      public void run() { 
       while (BUBBLING) { 
        moveBubble(); 

        try { 
         Thread.sleep(200); 
        } catch (InterruptedException e) { 

        } 

        //update by invalidating on main UI thread 
        handler.post(new Runnable() { 
         public void run() { 
          invalidate(); 
         } 
        }); 
       } 
      } 
     }).start(); 
    } 


    @Override 
    public void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     canvas.save(); 
     // draws bubble on canvas 
     canvas.translate(dx, dy); 
     bubble.draw(canvas); 
     canvas.restore(); 
    } 

    private void moveBubble(){ 
     dx += 1; 
     dy += 1; 
     x = x + dx; 
     y = y + dy; 
     if (bubble.getPaint().getColor() == Color.YELLOW){ 
      bubble.getPaint().setColor(Color.RED); 
     } else { 
      bubble.getPaint().setColor(Color.YELLOW); 
     } 
    } 
} 

Très apprécié,

+1

http://android-er.blogspot.com/2013/05/how-setretaininstancetrue-affect .html – tachyonflux

Répondre

3

Si vous voulez vraiment garder une vue entière, vous pouvez faire quelque chose comme une charge paresseuse:

public class BubbleFragment extends Fragment { 
    Bubble bubble; 
    LinearLayout parent; 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 

     setRetainInstance(true); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     parent = new LinearLayout(activity); 
     if(bubble == null) { 
      LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT, 
        ViewGroup.LayoutParams.MATCH_PARENT, 
        100); 
      bubble = new Bubble(getActivity()); 
      bubble.setLayoutParams(lp); 
      bubble.setBackgroundColor(Color.BLUE); 
     } 
     parent.setOrientation(LinearLayout.VERTICAL); 
     parent.addView(bubble); 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     parent.removeView(bubble); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     return parent; 
    } 
} 
+0

Cela fonctionne mais pourquoi créez-vous 2ice LinearLayour dans onAttach()? Je dirais que cela ne devrait être créé que lorsque la bulle est nulle – pixel

+1

Alors allez-y et faites-le – tachyonflux

+0

J'ai posté une autre question mais c'est juste légèrement différent. Au lieu de créer par programme la mise en page, j'ai ajouté le fichier de disposition qui héberge ma vue personnalisée Bubble. C'est ici http://stackoverflow.com/questions/33194087/retaining-fragment-with-custom-view Toute idée comment j'implémenterais la rétention dans ce cas. Je suis sûr que votre suggestion pour la charge paresseuse fonctionnerait mais j'essaye de m'en tenir à la tête et j'ai peu de succès. Très appréciée. – pixel

2

Dans votre cas, vous n'avez pas besoin setRetainInstance (true), il vous suffit d'enregistrer des variables d'instance dans onSaveInstanceState() et charge les dans onCreate(). Pour votre exemple, quelque chose comme:

public void onCreate(Bundle b) { 
    super.onCreate(b); 
    if(b != null) { 
     xPos = b.getInt("x"); 
     yPos = b.getInt("y"); 
    } 
} 

public void onSaveInstanceState(Bundle b) { 
    super.onSaveInstanceState(b); 
    b.putInt("x",xPos); 
    b.putInt("y",yPos); 
} 

Par ailleurs, la raison pour laquelle vous ne pouvez pas créer Bubble dans onCreate() est parce que le fragment est pas complètement associé à son activité jusqu'à onActivityCreated() est appelée, qui vient après onCreate() est appelée.

+0

Je connais onSaveInstanceState mais comme il y a beaucoup de variables, j'ai pensé que la simple conservation du fragment le résoudrait. Selon la documentation, la conservation devrait fonctionner aussi. Merci pour l'explication cependant. – pixel