保留片段

Retaining Fragment

我正在编写一个可以在 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);
        }
    }
}

非常感谢,

在你的情况下你不需要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 的原因是因为在调用 onActivityCreated() 之前,Fragment 没有与其 Activity 完全关联,这在调用 onCreate() 之后出现。

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

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