使用SurfaceView的SurfaceCreated不会被导航抽屉和片段调用

时间:2014-06-10 03:45:19

标签: android android-fragments bitmap surfaceview

我正在使用自定义SurfaceView类来尝试在屏幕上绘制位图。此外,我正在使用导航抽屉和片段来切换显示哪个SurfaceView。我知道这个部分正在工作,因为我为每个部分设置了不同的背景颜色,我看到了颜色的变化。问题是从不调用surfaceCreated()。我在该方法中为SurfaceView启动绘图线程,因此线程永远不会启动,并且永远不会绘制位图。

以下是我的主要活动中与片段切换相关的部分:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_screen);
}

private void selectItem(int position) {
    // update the main content by replacing fragments
    Fragment fragment = null;
    if(position ==0) {
        fragment = new MapFragment();
    } else {
        fragment = new TempFragment();
    }
    Bundle args = new Bundle();
    args.putInt(MapFragment.ARG_PLANET_NUMBER, position);
    fragment.setArguments(args);

    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();

    // update selected item and title, then close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(appScreens[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}


public static class MapFragment extends Fragment {

    public static String ARG_PLANET_NUMBER = "planet_number";

    public MapFragment() {
        // Empty constructor required for fragment subclasses
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_map_screen, container, false);
        MapSurfaceView bmpView = (MapSurfaceView) rootView.findViewById(R.id.bmpView);
        bmpView.setMap(map);
        return rootView;
    }
}

注意:MapFragment和TempFragment的背景颜色不同。

主要活动布局:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- android:layout_gravity="start" tells DrawerLayout to treat
         this as a sliding drawer on the left side for left-to-right
         languages and on the right side for right-to-left languages.
         If you're not building against API 17 or higher, use
         android:layout_gravity="left" instead. -->
    <!-- The drawer is given a fixed width in dp and extends the full height of
         the container. -->

    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#cccc" />

</android.support.v4.widget.DrawerLayout>

SurfaceView:

class MapSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    class MapThread extends Thread {

        private Context mContext;

        /**
         * Handle to the surface manager object we interact with
         */
        private SurfaceHolder mSurfaceHolder;

        /*
         * State-tracking constants
         */
        public static final int STATE_PAUSE = 1;
        public static final int STATE_RUNNING = 2;

        /**
         * The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN
         */
        private int mMode;

        /**
         * Indicate whether the surface has been created & is ready to draw
         */
        private boolean mRun = false;

        public MapThread(SurfaceHolder surfaceHolder, Context context) {
            // get handles to some important objects
            mSurfaceHolder = surfaceHolder;
            mContext = context;
        }

        /**
         * Starts the game, setting parameters for the current difficulty.
         */
        public void doStart() {
            synchronized (mSurfaceHolder) {
                setState(STATE_RUNNING);
            }
        }

        /**
         * Pauses the physics update & animation.
         */
        public void pause() {
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) setState(STATE_PAUSE);
            }
        }

        /**
         * Restores game state from the indicated Bundle. Typically called when
         * the Activity is being restored after having been previously
         * destroyed.
         *
         * @param savedState Bundle containing the game state
         */
        public synchronized void restoreState(Bundle savedState) {
            synchronized (mSurfaceHolder) {
                setState(STATE_PAUSE);
            }
        }

        @Override
        public void run() {
            while (mRun) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        if (mMode == STATE_RUNNING)
                        doDraw(c);
                    }
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

        /**
         * Dump game state to the provided Bundle. Typically called when the
         * Activity is being suspended.
         *
         * @return Bundle with this view's state
         */
        public Bundle saveState(Bundle map) {
            synchronized (mSurfaceHolder) {
            }
            return map;
        }

        /**
         * Used to signal the thread whether it should be running or not.
         * Passing true allows the thread to run; passing false will shut it
         * down if it's already running. Calling start() after this was most
         * recently called with false will result in an immediate shutdown.
         *
         * @param b true to run, false to shut down
         */
        public void setRunning(boolean b) {
            mRun = b;
        }

        /**
         * Sets the game mode. That is, whether we are running, paused, in the
         * failure state, in the victory state, etc.
         *
         * @param mode one of the STATE_* constants
         */
        public void setState(int mode) {
            synchronized (mSurfaceHolder) {
                mMode = mode;
            }
        }

        /**
         * Resumes from a pause.
         */
        public void unpause() {
            // Move the real time clock up to now
            synchronized (mSurfaceHolder) {
            }
            setState(STATE_RUNNING);
        }

        /**
         * Draws the ship, fuel/speed bars, and background to the provided
         * Canvas.
         */
        private void doDraw(Canvas canvas) {
            Bitmap mapBMP = map.getMapBitmap().copy(Bitmap.Config.ARGB_8888, true);
            //System.out.println(mapBMP.describeContents());
            canvas.setBitmap(mapBMP);
        }
    }

    private Map map = null;
    private Context mContext;
    private MapThread thread;

    private Object mPauseLock;
    private boolean mPaused;
    private boolean mFinished;
    private boolean running = false;

    public MapSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        // create thread only; it's started in surfaceCreated()
        thread = new MapThread(holder, context);
        setFocusable(true);
    }

    public MapThread getThread(){
        return thread;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public void onFinishInflate() {
        System.out.println("Inflated");
    }

    public void onAttachedToWindow(){
        System.out.println("Attached");
    }

    public void onDetachedFromWindow(){
        System.out.println("Detached");
    }

    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        if (!hasWindowFocus) thread.pause();
        else thread.unpause();
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        System.out.println("Surface created");
        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }
}

SurfaceView布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wrathfulape.supremacy.MainScreen$PlaceholderFragment">

    <com.wrathfulape.supremacy.MapSurfaceView
        android:id="@+id/bmpView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

0 个答案:

没有答案