Android Full Screen Activity to View Zoomable Image

July 21, 2018
using Glide and PhotoView

The following library are used

The activity shall have the following features

  • Full screen: no status bar
  • Action toolbar shall overlay the image: maintain back icon to close the activity
  • Click the on image will toggle dark mode (background change to dark color and hide toolbar)
  • Image shown shall be zoomable

Enable Fullscreen Mode

Edit AndroidManifest.xml

<manifest ...>
    <application ...>
        <activity
            android:name=".view.support.ImageViewActivity"
            android:label="@string/title_activity_image_view"
            android:parentActivityName=".MainActivity"
            android:theme="@style/AppTheme.Fullscreen">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".MainActivity" />
        </activity>
    </application>
</manifest>

Edit res/values/styles.xml.

<resources>
    <style name="AppTheme.Fullscreen">
        <item name="android:windowFullscreen">true</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>
</resources>    

Activity and layout

Code of ImageViewActivity.

ViewModel is used to maintain Dark Mode status to survice screen rotation/configuration change.

NOTE: Optional ViewModel and Dagger2 dependency injection is used. You can remove them.

class ImageViewActivity : AppCompatActivity() {
    companion object {
        private const val EXTRA_IMAGE_RESOURCE = "image_resource"

        fun newInstance(context: Context, imageResource: String) = Intent(context, ImageViewActivity::class.java).apply {
            // imageResource can be file path or URL
            putExtra(EXTRA_IMAGE_RESOURCE, imageResource)
        }
    }

    @Inject
    lateinit var viewModelFactory: ViewModelFactory
    private lateinit var viewModel: ImageViewViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_image_view)
        setSupportActionBar(toolbar)

        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        viewModel = ViewModelProviders.of(this, viewModelFactory).get(ImageViewViewModel::class.java)

        val imageResource = intent.getStringExtra(EXTRA_IMAGE_RESOURCE)

        GlideApp.with(this)
                .load(imageResource)
                // .override(SimpleTarget.SIZE_ORIGINAL, SimpleTarget.SIZE_ORIGINAL)
                .into(photoView)

        photoView.setOnClickListener {
            viewModel.darkMode.value = !(viewModel.darkMode.value ?: false)
        }

        viewModel.darkMode.observe(this, Observer {
            it?.also {
                val color = if (it) {
                    toolbar.isVisible = false
                    android.R.color.black

                }
                else {
                    toolbar.isVisible = true
                    android.R.color.white
                }
                container.setBackgroundColor(ContextCompat.getColor(context, color))
            }
        })
    }

    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }
}
class ImageViewViewModel @Inject constructor(private val db: AppDatabase): ViewModel() {
    internal val darkMode = MutableLiveData<Boolean>()

    init {
        darkMode.value = false
    }
}

activity_image_view.xml

  • Change AppBarLayout to transparent background.
  • Don’t apply app:layout_behavior="@string/appbar_scrolling_view_behavior" to content (ensure content can be fullscreen without restriction of AppBarLayout)
  • Put AppBarLayout after content (PhotoView), else toolbar button are not clickable.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".view.support.ImageViewActivity">

    <!--
    <include layout="@layout/content_image_view" />
     -->

    <!-- app:layout_behavior="@string/appbar_scrolling_view_behavior" -->
    <com.github.chrisbanes.photoview.PhotoView
        android:id="@+id/photoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        />

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay.Light"
        android:background="@android:color/transparent"
        app:elevation="0dp">

        <!-- android:background="?attr/colorPrimary" -->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <!--
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />
        -->

</android.support.design.widget.CoordinatorLayout>
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.