moagrius / TileView

TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like markers, hotspots, and path drawing.
MIT License
1.46k stars 337 forks source link

TileView not refreshing when configuration changes are manually handled #41

Closed ghost closed 10 years ago

ghost commented 11 years ago

If the TileView is in an activity defined as:

<activity
            android:name="com.example.MainActivity"
            android:screenOrientation="fullSensor"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustResize"
            android:label="@string/app_name" >

and the scale level is 0 (or min) then the TileView doesn't refresh properly on device orientation change. I've tried adding following code, but it does not help:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // refresh map
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE || newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            tileView.refresh();
        }
    }

More to say, panning the view after orientation change doesnt invalidate the tiles, only zooming in invalidates them actually.

moagrius commented 11 years ago

You'd have to do some extending to handle configChanges to the TileView in the Activity. As is, the safest approach is not use configChanges and allow normal destruction and resumption cycles, like so:

@Override
public void onPause() {
    super.onPause();
    tileView.clear();
}

@Override
public void onResume() {
    super.onResume();
    tileView.resume();
}

@Override
public void onDestroy() {
    super.onDestroy();
    tileView.destroy();
    tileView = null;
}

You could save the scale and scroll position and reset those in onResume if you wanted a more seamless effect, but that's not included by default.

ghost commented 10 years ago

After a little experimentation I've found that this helps (if the tileview is within fairly simple layout) in TileView.java,730:

    private Runnable mRefreshRunnable = new Runnable(){
        @Override
        public void run() {
            refresh();
        }
    };

    // make sure we keep the viewport UTD, and if layout changes we'll need to recompute what tiles to show
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout( changed, l, t, r, b );
        if ( changed ) {            
            updateViewport();
            // modified below
            // requestRender();
            tileManager.clear();
            postDelayed(mRefreshRunnable, 1);
        }
    }

Now this might not work if the tileview is within some complex layout, although I havent tested so cant verify. The code above is just a suggestion and needs to be thoroughly tested (albeit it does the job for me on a simple layout, tested with multiple devices).

moagrius commented 10 years ago

I might add this as a user-configurable setting at some point, but closing the issue for now, since you seem to have a workable hack.