保留片段

时间:2015-10-15 22:45:55

标签: android fragment device-orientation

我正在编写一个可以在Canvas上绘制气泡的应用。 我有MainActivity,它的布局是一个简单的LinearLayout,我用它作为片段的持有者。 我的片段没有xml布局,因为我在Canvas上绘图,所以我以编程方式设置它的布局:

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;
    }
}

所以,当我启动我的应用程序时,我预计会在屏幕中间显示气泡并慢慢向底部移动。由于我使用上面的setRetainInstance(true),我希望当我旋转屏幕时,气泡会在旋转之前从中断处继续。但是,它会在初始位置(屏幕中间)重绘。

我想继续从屏幕方向改变之前的位置开始,而不是从一开始。

这是我的泡泡代码:

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);
        }
    }
}

非常感谢,

2 个答案:

答案 0 :(得分:3)

如果你真的想要保留整个视图,你可以做一些类似延迟加载的事情:

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;
    }
}

答案 1 :(得分:2)

在您的情况下,您不需要setRetainInstance(true),您只需要在onSaveInstanceState()中保存实例变量并将它们加载到onCreate()中。对于您的示例,例如:

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);
}

顺便说一句,你不能在onCreate()中创建Bubble的原因是因为在调用onCreate()之后调用onActivityCreated()之前,Fragment与其Activity没有完全关联。