Compare commits
	
		
			1 Commits
		
	
	
		
			v172012358
			...
			v172012358
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 918661be2d | 
@@ -138,6 +138,9 @@ dependencies {
 | 
			
		||||
    // Pager
 | 
			
		||||
    implementation 'me.relex:circleindicator:2.0.0@aar'
 | 
			
		||||
 | 
			
		||||
    //PhotoView
 | 
			
		||||
    implementation 'com.github.chrisbanes:PhotoView:2.0.0'
 | 
			
		||||
 | 
			
		||||
    implementation 'androidx.core:core-ktx:1.1.0-beta01'
 | 
			
		||||
 | 
			
		||||
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,9 @@
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".ReaderActivity">
 | 
			
		||||
        </activity>
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".ImageActivity">
 | 
			
		||||
        </activity>
 | 
			
		||||
 | 
			
		||||
        <meta-data
 | 
			
		||||
            android:name="apps.amine.bou.readerforselfoss.utils.glide.SelfSignedGlideModule"
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,52 @@
 | 
			
		||||
package apps.amine.bou.readerforselfoss
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.MenuItem
 | 
			
		||||
import androidx.appcompat.app.AppCompatActivity
 | 
			
		||||
import androidx.fragment.app.FragmentManager
 | 
			
		||||
import androidx.fragment.app.FragmentStatePagerAdapter
 | 
			
		||||
import apps.amine.bou.readerforselfoss.fragments.ImageFragment
 | 
			
		||||
import kotlinx.android.synthetic.main.activity_reader.*
 | 
			
		||||
 | 
			
		||||
class ImageActivity : AppCompatActivity() {
 | 
			
		||||
    private lateinit var allImages : ArrayList<String>
 | 
			
		||||
    private var position : Int = 0
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        setContentView(R.layout.activity_image)
 | 
			
		||||
 | 
			
		||||
        setSupportActionBar(toolBar)
 | 
			
		||||
        supportActionBar?.setDisplayShowTitleEnabled(false)
 | 
			
		||||
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
 | 
			
		||||
 | 
			
		||||
        allImages = intent.getStringArrayListExtra("allImages")
 | 
			
		||||
        position = intent.getIntExtra("position", 0)
 | 
			
		||||
 | 
			
		||||
        pager.adapter = ScreenSlidePagerAdapter(supportFragmentManager)
 | 
			
		||||
        pager.currentItem = position
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
        when (item.itemId) {
 | 
			
		||||
            android.R.id.home -> {
 | 
			
		||||
                onBackPressed()
 | 
			
		||||
                return true
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return super.onOptionsItemSelected(item)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
 | 
			
		||||
 | 
			
		||||
        override fun getCount(): Int {
 | 
			
		||||
            return allImages.size
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        override fun getItem(position: Int): ImageFragment {
 | 
			
		||||
            return ImageFragment.newInstance(allImages[position])
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,9 +5,14 @@ import android.net.Uri
 | 
			
		||||
import android.os.Parcel
 | 
			
		||||
import android.os.Parcelable
 | 
			
		||||
import android.text.Html
 | 
			
		||||
import android.webkit.URLUtil
 | 
			
		||||
import org.jsoup.Jsoup
 | 
			
		||||
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.Config
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
 | 
			
		||||
import com.bumptech.glide.request.RequestOptions
 | 
			
		||||
import com.google.gson.annotations.SerializedName
 | 
			
		||||
 | 
			
		||||
private fun constructUrl(config: Config?, path: String, file: String?): String {
 | 
			
		||||
@@ -128,6 +133,36 @@ data class Item(
 | 
			
		||||
        return constructUrl(config, "thumbnails", thumbnail)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getImages() : ArrayList<String> {
 | 
			
		||||
        var allImages = ArrayList<String>()
 | 
			
		||||
 | 
			
		||||
        for ( image in Jsoup.parse(content).getElementsByTag("img")) {
 | 
			
		||||
            allImages.add(image.attr("src"))
 | 
			
		||||
        }
 | 
			
		||||
        return allImages
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun preloadImages(context: Context) : Boolean {
 | 
			
		||||
        val imageUrls = this.getImages()
 | 
			
		||||
 | 
			
		||||
        val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            for (url in imageUrls) {
 | 
			
		||||
                if ( URLUtil.isValidUrl(url)) {
 | 
			
		||||
                    val image = Glide.with(context).asBitmap()
 | 
			
		||||
                            .apply(glideOptions)
 | 
			
		||||
                            .load(url).submit().get()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e : Error) {
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getTitleDecoded(): String {
 | 
			
		||||
        return Html.fromHtml(title).toString()
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,7 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con
 | 
			
		||||
                                    notificationManager.notify(2, newItemsNotification.build())
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                            apiItems.map {it.preloadImages(context)}
 | 
			
		||||
                        }
 | 
			
		||||
                        Timer("", false).schedule(4000) {
 | 
			
		||||
                            notificationManager.cancel(1)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +1,28 @@
 | 
			
		||||
package apps.amine.bou.readerforselfoss.fragments
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.content.SharedPreferences
 | 
			
		||||
import android.content.res.ColorStateList
 | 
			
		||||
import android.content.res.TypedArray
 | 
			
		||||
import android.graphics.Bitmap
 | 
			
		||||
import android.graphics.Typeface
 | 
			
		||||
import android.graphics.drawable.ColorDrawable
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.preference.PreferenceManager
 | 
			
		||||
import android.view.InflateException
 | 
			
		||||
import android.view.*
 | 
			
		||||
import android.webkit.*
 | 
			
		||||
import androidx.browser.customtabs.CustomTabsIntent
 | 
			
		||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import androidx.core.content.ContextCompat
 | 
			
		||||
import androidx.core.widget.NestedScrollView
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.MenuItem
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.webkit.WebSettings
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import androidx.core.content.res.ResourcesCompat
 | 
			
		||||
import androidx.room.Room
 | 
			
		||||
import apps.amine.bou.readerforselfoss.ImageActivity
 | 
			
		||||
import apps.amine.bou.readerforselfoss.R
 | 
			
		||||
import apps.amine.bou.readerforselfoss.api.mercury.MercuryApi
 | 
			
		||||
import apps.amine.bou.readerforselfoss.api.mercury.ParsedContent
 | 
			
		||||
@@ -39,6 +39,7 @@ import apps.amine.bou.readerforselfoss.utils.Config
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.buildCustomTabsIntent
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.customtabs.CustomTabActivityHelper
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.glide.loadMaybeBasicAuth
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.glide.getBitmapInputStream
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.isEmptyOrNullOrNullString
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.network.isNetworkAccessible
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.openItemUrl
 | 
			
		||||
@@ -46,6 +47,7 @@ import apps.amine.bou.readerforselfoss.utils.shareLink
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.sourceAndDateText
 | 
			
		||||
import apps.amine.bou.readerforselfoss.utils.succeeded
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
 | 
			
		||||
import com.bumptech.glide.request.RequestOptions
 | 
			
		||||
import com.github.rubensousa.floatingtoolbar.FloatingToolbar
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_article.view.*
 | 
			
		||||
@@ -54,6 +56,8 @@ import retrofit2.Callback
 | 
			
		||||
import retrofit2.Response
 | 
			
		||||
import java.net.MalformedURLException
 | 
			
		||||
import java.net.URL
 | 
			
		||||
import java.util.concurrent.ExecutionException
 | 
			
		||||
import kotlin.collections.ArrayList
 | 
			
		||||
import kotlin.concurrent.thread
 | 
			
		||||
 | 
			
		||||
class ArticleFragment : Fragment() {
 | 
			
		||||
@@ -66,6 +70,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
    private lateinit var contentSource: String
 | 
			
		||||
    private lateinit var contentImage: String
 | 
			
		||||
    private lateinit var contentTitle: String
 | 
			
		||||
    private lateinit var allImages : ArrayList<String>
 | 
			
		||||
    private lateinit var editor: SharedPreferences.Editor
 | 
			
		||||
    private lateinit var fab: FloatingActionButton
 | 
			
		||||
    private lateinit var appColors: AppColors
 | 
			
		||||
@@ -117,6 +122,7 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
            contentTitle = allItems[pageNumber.toInt()].getTitleDecoded()
 | 
			
		||||
            contentImage = allItems[pageNumber.toInt()].getThumbnail(activity!!)
 | 
			
		||||
            contentSource = allItems[pageNumber.toInt()].sourceAndDateText()
 | 
			
		||||
            allImages = allItems[pageNumber.toInt()].getImages()
 | 
			
		||||
 | 
			
		||||
            prefs = PreferenceManager.getDefaultSharedPreferences(activity)
 | 
			
		||||
            editor = prefs.edit()
 | 
			
		||||
@@ -411,6 +417,47 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
        rootView!!.webcontent.settings.loadWithOverviewMode = true
 | 
			
		||||
        rootView!!.webcontent.settings.javaScriptEnabled = false
 | 
			
		||||
 | 
			
		||||
        rootView!!.webcontent.webViewClient = object : WebViewClient() {
 | 
			
		||||
            override fun shouldOverrideUrlLoading(view: WebView?, url : String): Boolean {
 | 
			
		||||
                if (rootView!!.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
 | 
			
		||||
                    rootView!!.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
 | 
			
		||||
                }
 | 
			
		||||
                return true
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
 | 
			
		||||
                val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
 | 
			
		||||
                if (url.toLowerCase().contains(".jpg") || url.toLowerCase().contains(".jpeg")) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
 | 
			
		||||
                        return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.JPEG))
 | 
			
		||||
                    }catch ( e : ExecutionException) {}
 | 
			
		||||
                }
 | 
			
		||||
                else if (url.toLowerCase().contains(".png")) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
 | 
			
		||||
                        return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.PNG))
 | 
			
		||||
                    }catch ( e : ExecutionException) {}
 | 
			
		||||
                }
 | 
			
		||||
                else if (url.toLowerCase().contains(".webp")) {
 | 
			
		||||
                    try {
 | 
			
		||||
                        val image = Glide.with(view).asBitmap().apply(glideOptions).load(url).submit().get()
 | 
			
		||||
                        return WebResourceResponse("image/jpg", "UTF-8", getBitmapInputStream(image, Bitmap.CompressFormat.WEBP))
 | 
			
		||||
                    }catch ( e : ExecutionException) {}
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return super.shouldInterceptRequest(view, url)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val gestureDetector = GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
 | 
			
		||||
            override fun onSingleTapUp(e: MotionEvent?): Boolean {
 | 
			
		||||
                return performClick()
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        rootView!!.webcontent.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event)}
 | 
			
		||||
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
 | 
			
		||||
            rootView!!.webcontent.settings.layoutAlgorithm =
 | 
			
		||||
                    WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING
 | 
			
		||||
@@ -526,5 +573,20 @@ class ArticleFragment : Fragment() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun performClick(): Boolean {
 | 
			
		||||
        if (rootView!!.webcontent.hitTestResult.type == WebView.HitTestResult.IMAGE_TYPE ||
 | 
			
		||||
                rootView!!.webcontent.hitTestResult.type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
 | 
			
		||||
 | 
			
		||||
            val position : Int = allImages.indexOf(rootView!!.webcontent.hitTestResult.extra)
 | 
			
		||||
 | 
			
		||||
            val intent = Intent(activity, ImageActivity::class.java)
 | 
			
		||||
            intent.putExtra("allImages", allImages)
 | 
			
		||||
            intent.putExtra("position", position)
 | 
			
		||||
            startActivity(intent)
 | 
			
		||||
            return false
 | 
			
		||||
        }
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
package apps.amine.bou.readerforselfoss.fragments
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.*
 | 
			
		||||
import androidx.fragment.app.Fragment
 | 
			
		||||
import apps.amine.bou.readerforselfoss.R
 | 
			
		||||
import com.bumptech.glide.Glide
 | 
			
		||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
 | 
			
		||||
import com.bumptech.glide.request.RequestOptions
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_image.view.*
 | 
			
		||||
 | 
			
		||||
class ImageFragment : Fragment() {
 | 
			
		||||
 | 
			
		||||
    private lateinit var imageUrl : String
 | 
			
		||||
    private val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        imageUrl = arguments!!.getString("imageUrl")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
 | 
			
		||||
        val view : View = inflater.inflate(R.layout.fragment_image, container, false)
 | 
			
		||||
 | 
			
		||||
        view.photoView.visibility = View.VISIBLE
 | 
			
		||||
        Glide.with(activity)
 | 
			
		||||
                .asBitmap()
 | 
			
		||||
                .apply(glideOptions)
 | 
			
		||||
                .load(imageUrl)
 | 
			
		||||
                .into(view.photoView)
 | 
			
		||||
 | 
			
		||||
        return view
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private const val ARG_IMAGE = "imageUrl"
 | 
			
		||||
 | 
			
		||||
        fun newInstance(
 | 
			
		||||
                imageUrl : String
 | 
			
		||||
        ): ImageFragment {
 | 
			
		||||
            val fragment = ImageFragment()
 | 
			
		||||
            val args = Bundle()
 | 
			
		||||
            args.putString(ARG_IMAGE, imageUrl)
 | 
			
		||||
            fragment.arguments = args
 | 
			
		||||
            return fragment
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,6 +14,9 @@ import com.bumptech.glide.load.model.GlideUrl
 | 
			
		||||
import com.bumptech.glide.load.model.LazyHeaders
 | 
			
		||||
import com.bumptech.glide.request.RequestOptions
 | 
			
		||||
import com.bumptech.glide.request.target.BitmapImageViewTarget
 | 
			
		||||
import java.io.ByteArrayInputStream
 | 
			
		||||
import java.io.ByteArrayOutputStream
 | 
			
		||||
import java.io.InputStream
 | 
			
		||||
 | 
			
		||||
fun Context.bitmapCenterCrop(config: Config, url: String, iv: ImageView) =
 | 
			
		||||
    Glide.with(this)
 | 
			
		||||
@@ -56,4 +59,11 @@ fun RequestManager.loadMaybeBasicAuth(config: Config, url: String): RequestBuild
 | 
			
		||||
    }
 | 
			
		||||
    val glideUrl = GlideUrl(url, builder.build())
 | 
			
		||||
    return this.load(glideUrl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun getBitmapInputStream(bitmap:Bitmap,compressFormat: Bitmap.CompressFormat): InputStream {
 | 
			
		||||
    val byteArrayOutputStream = ByteArrayOutputStream()
 | 
			
		||||
    bitmap.compress(compressFormat, 80, byteArrayOutputStream)
 | 
			
		||||
    val bitmapData: ByteArray = byteArrayOutputStream.toByteArray()
 | 
			
		||||
    return ByteArrayInputStream(bitmapData)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								app/src/main/res/layout/activity_image.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/src/main/res/layout/activity_image.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.appbar.AppBarLayout
 | 
			
		||||
        android:id="@+id/appBarLayout"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toTopOf="parent">
 | 
			
		||||
 | 
			
		||||
        <androidx.appcompat.widget.Toolbar
 | 
			
		||||
            android:id="@+id/toolBar"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="?attr/actionBarSize"
 | 
			
		||||
            app:popupTheme="?attr/toolbarPopupTheme"
 | 
			
		||||
            app:theme="@style/ToolBarStyle" />
 | 
			
		||||
 | 
			
		||||
    </com.google.android.material.appbar.AppBarLayout>
 | 
			
		||||
 | 
			
		||||
    <androidx.viewpager.widget.ViewPager
 | 
			
		||||
        android:id="@+id/pager"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="0dp"
 | 
			
		||||
        app:layout_constraintBottom_toBottomOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@+id/appBarLayout" />
 | 
			
		||||
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
							
								
								
									
										16
									
								
								app/src/main/res/layout/fragment_image.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/src/main/res/layout/fragment_image.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    <com.github.chrisbanes.photoview.PhotoView
 | 
			
		||||
        android:id="@+id/photoView"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:layout_centerVertical="true"
 | 
			
		||||
        android:layout_centerHorizontal="true"
 | 
			
		||||
        android:background="@android:color/black"
 | 
			
		||||
        app:srcCompat="@android:drawable/screen_background_dark" />
 | 
			
		||||
 | 
			
		||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
 | 
			
		||||
		Reference in New Issue
	
	Block a user