parent
a307f35346
commit
4863dfb2e8
Binary file not shown.
|
@ -5,8 +5,11 @@ import android.graphics.*
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.ImageView
|
||||||
import androidx.annotation.RawRes
|
import androidx.annotation.RawRes
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import oupson.apng.chunks.IHDR
|
import oupson.apng.chunks.IHDR
|
||||||
import oupson.apng.chunks.fcTL
|
import oupson.apng.chunks.fcTL
|
||||||
|
@ -23,6 +26,11 @@ import java.util.zip.CRC32
|
||||||
|
|
||||||
// TODO DOC CODE
|
// TODO DOC CODE
|
||||||
class ExperimentalApngDecoder {
|
class ExperimentalApngDecoder {
|
||||||
|
interface Callback {
|
||||||
|
fun onSuccess(drawable : Drawable)
|
||||||
|
fun onError(error : java.lang.Exception)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// TODO Change TAG
|
// TODO Change TAG
|
||||||
private const val TAG = "ExperimentalApngDecoder"
|
private const val TAG = "ExperimentalApngDecoder"
|
||||||
|
@ -365,6 +373,159 @@ class ExperimentalApngDecoder {
|
||||||
decodeApng(FileInputStream(Loader.load(context, url)), speed)
|
decodeApng(FileInputStream(Loader.load(context, url)), speed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Apng into an imageView, asynchronously
|
||||||
|
* @param file File to decode.
|
||||||
|
* @param imageView Image View.
|
||||||
|
* @param speed Optional parameter.
|
||||||
|
* @param callback [ExperimentalApngDecoder.Callback] to handle success and error
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun decodeApngAsyncInto(file : File, imageView : ImageView, speed: Float = 1f, callback: Callback? = null) {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val drawable = decodeApng(FileInputStream(file), speed)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
imageView.setImageDrawable(drawable)
|
||||||
|
(drawable as? CustomAnimationDrawable)?.start()
|
||||||
|
callback?.onSuccess(drawable)
|
||||||
|
}
|
||||||
|
} catch (e : java.lang.Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Apng into an imageView, asynchronously
|
||||||
|
* @param context Context
|
||||||
|
* @param uri Uri to load
|
||||||
|
* @param imageView Image View.
|
||||||
|
* @param speed Optional parameter.
|
||||||
|
* @param callback [ExperimentalApngDecoder.Callback] to handle success and error
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun decodeApngAsyncInto(context : Context, uri : Uri, imageView: ImageView, speed: Float = 1f, callback: Callback? = null) {
|
||||||
|
val inputStream = context.contentResolver.openInputStream(uri) ?: throw Exception("Failed to open InputStream, InputStream is null")
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val drawable = decodeApng(inputStream, speed)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
imageView.setImageDrawable(drawable)
|
||||||
|
(drawable as? CustomAnimationDrawable)?.start()
|
||||||
|
callback?.onSuccess(drawable)
|
||||||
|
}
|
||||||
|
} catch (e : java.lang.Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Apng into an imageView, asynchronously
|
||||||
|
* @param context Context
|
||||||
|
* @param res Raw resource to load
|
||||||
|
* @param imageView Image View.
|
||||||
|
* @param speed Optional parameter.
|
||||||
|
* @param callback [ExperimentalApngDecoder.Callback] to handle success and error
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun decodeApngAsyncInto(context : Context, @RawRes res : Int, imageView: ImageView, speed: Float = 1f, callback: Callback? = null) {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val drawable = decodeApng(context.resources.openRawResource(res), speed)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
imageView.setImageDrawable(drawable)
|
||||||
|
(drawable as? CustomAnimationDrawable)?.start()
|
||||||
|
callback?.onSuccess(drawable)
|
||||||
|
}
|
||||||
|
} catch (e : java.lang.Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Apng into an imageView, asynchronously
|
||||||
|
* @param context Context
|
||||||
|
* @param url URL to load
|
||||||
|
* @param imageView Image View.
|
||||||
|
* @param speed Optional parameter.
|
||||||
|
* @param callback [ExperimentalApngDecoder.Callback] to handle success and error
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun decodeApngAsyncInto(context : Context, url : URL, imageView: ImageView, speed: Float = 1f, callback: Callback? = null) {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val drawable = decodeApng(FileInputStream(Loader.load(context, url)), speed)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
imageView.setImageDrawable(drawable)
|
||||||
|
(drawable as? CustomAnimationDrawable)?.start()
|
||||||
|
callback?.onSuccess(drawable)
|
||||||
|
}
|
||||||
|
} catch (e : java.lang.Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Apng into an imageView, asynchronously
|
||||||
|
* @param context Context
|
||||||
|
* @param string URL to load
|
||||||
|
* @param imageView Image View.
|
||||||
|
* @param speed Optional parameter.
|
||||||
|
* @param callback [ExperimentalApngDecoder.Callback] to handle success and error
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
|
fun decodeApngAsyncInto(context : Context, string: String, imageView: ImageView, speed: Float = 1f, callback: Callback? = null) {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
if (string.startsWith("http://") || string.startsWith("https://")) {
|
||||||
|
decodeApngAsyncInto(context, URL(string), imageView, speed, callback)
|
||||||
|
} else if(File(string).exists()) {
|
||||||
|
var pathToLoad = if (string.startsWith("content://")) string else "file://$string"
|
||||||
|
pathToLoad = pathToLoad.replace("%", "%25").replace("#", "%23")
|
||||||
|
decodeApngAsyncInto(context, Uri.parse(pathToLoad), imageView, speed, callback)
|
||||||
|
} else if (string.startsWith("file://android_asset/")) {
|
||||||
|
val drawable = decodeApng(context.assets.open(string.replace("file:///android_asset/", "")), speed)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
imageView.setImageDrawable(drawable)
|
||||||
|
(drawable as? CustomAnimationDrawable)?.start()
|
||||||
|
callback?.onSuccess(drawable)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(java.lang.Exception("Cannot open string"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e : java.lang.Exception) {
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
callback?.onError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a correct IHDR from the IHDR chunk of the APNG
|
* Generate a correct IHDR from the IHDR chunk of the APNG
|
||||||
* @param ihdrOfApng The IHDR of the APNG
|
* @param ihdrOfApng The IHDR of the APNG
|
||||||
|
|
|
@ -5,7 +5,6 @@ import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
class Loader {
|
class Loader {
|
||||||
|
@ -16,22 +15,23 @@ class Loader {
|
||||||
* @param url Url of the file to download
|
* @param url Url of the file to download
|
||||||
* @return [ByteArray] of the file
|
* @return [ByteArray] of the file
|
||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
// @Throws(IOException::class, java.io.FileNotFoundException::class, java.lang.Exception::class)
|
||||||
suspend fun load(context: Context, url: URL): File = withContext(Dispatchers.IO) {
|
suspend fun load(context: Context, url: URL) =
|
||||||
val currentDir = context.filesDir
|
withContext(Dispatchers.IO) {
|
||||||
val fileTXT = File(currentDir, "apngLoader.txt")
|
val currentDir = context.filesDir
|
||||||
val filePNG = File(currentDir, "apngLoader.png")
|
val fileTXT = File(currentDir, "apngLoader.txt")
|
||||||
if (fileTXT.exists() && url.toString() == fileTXT.readText()) {
|
val filePNG = File(currentDir, "apngLoader.png")
|
||||||
filePNG
|
if (fileTXT.exists() && url.toString() == fileTXT.readText()) {
|
||||||
} else {
|
filePNG
|
||||||
val connection = url.openConnection()
|
} else {
|
||||||
connection.connect()
|
val connection = url.openConnection()
|
||||||
val input = BufferedInputStream(connection.getInputStream())
|
connection.connect()
|
||||||
val bytes = input.readBytes()
|
val input = BufferedInputStream(connection.getInputStream())
|
||||||
input.close()
|
val bytes = input.readBytes()
|
||||||
fileTXT.writeText(url.toString())
|
input.close()
|
||||||
filePNG.apply { writeBytes(bytes) }
|
fileTXT.writeText(url.toString())
|
||||||
|
filePNG.apply { writeBytes(bytes) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package oupson.apngcreator
|
||||||
|
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import oupson.apng.ExperimentalApngDecoder
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
|
class ApngDecoderFragment : Fragment() {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "ApngDecoderFragment"
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance() =
|
||||||
|
ApngDecoderFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
// Inflate the layout for this fragment
|
||||||
|
val view = inflater.inflate(R.layout.fragment_apng_decoder, container, false)
|
||||||
|
|
||||||
|
val imageView : ImageView = view.findViewById(R.id.apngDecoderImageView) ?: return view
|
||||||
|
|
||||||
|
if (context != null) {
|
||||||
|
ExperimentalApngDecoder.decodeApngAsyncInto(
|
||||||
|
this.context!!,
|
||||||
|
URL("http://littlesvr.ca/apng/images/GenevaDrive.png"),
|
||||||
|
imageView,
|
||||||
|
callback = object : ExperimentalApngDecoder.Callback {
|
||||||
|
override fun onSuccess(drawable: Drawable) {
|
||||||
|
if (BuildConfig.DEBUG)
|
||||||
|
Log.i(TAG, "onSuccess()")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(error: Exception) {
|
||||||
|
if (BuildConfig.DEBUG)
|
||||||
|
Log.e(TAG, "onError", error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package oupson.apngcreator;
|
package oupson.apngcreator;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -10,9 +12,9 @@ import android.widget.ImageView;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import kotlin.Unit;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import oupson.apng.ApngAnimator;
|
|
||||||
import oupson.apng.ApngAnimatorKt;
|
import oupson.apng.ExperimentalApngDecoder;
|
||||||
|
|
||||||
|
|
||||||
public class JavaFragment extends Fragment {
|
public class JavaFragment extends Fragment {
|
||||||
|
@ -22,10 +24,16 @@ public class JavaFragment extends Fragment {
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
Log.i(TAG, "onCreateView()");
|
Log.i(TAG, "onCreateView()");
|
||||||
|
|
||||||
View v = inflater.inflate(R.layout.fragment_java, container, false);
|
View v = inflater.inflate(R.layout.fragment_java, container, false);
|
||||||
|
|
||||||
String imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png";
|
String imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png";
|
||||||
ImageView imageView = v.findViewById(R.id.javaImageView);
|
ImageView imageView = v.findViewById(R.id.javaImageView);
|
||||||
if (imageView != null) {
|
|
||||||
|
Context context = this.getContext();
|
||||||
|
|
||||||
|
if (imageView != null && context != null) {
|
||||||
|
/*
|
||||||
ApngAnimator a = ApngAnimatorKt.loadApng(imageView, imageUrl);
|
ApngAnimator a = ApngAnimatorKt.loadApng(imageView, imageUrl);
|
||||||
a.onLoaded((animator) -> {
|
a.onLoaded((animator) -> {
|
||||||
animator.setOnFrameChangeLister((index) -> {
|
animator.setOnFrameChangeLister((index) -> {
|
||||||
|
@ -36,6 +44,19 @@ public class JavaFragment extends Fragment {
|
||||||
});
|
});
|
||||||
return Unit.INSTANCE;
|
return Unit.INSTANCE;
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
ExperimentalApngDecoder.decodeApngAsyncInto(context, imageUrl, imageView, 1f, new ExperimentalApngDecoder.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NotNull Drawable drawable) {
|
||||||
|
Log.i(TAG, "Success");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NotNull Exception error) {
|
||||||
|
Log.e(TAG, "Error", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ import org.jetbrains.anko.startActivity
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MainActivity"
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -39,7 +42,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
navigationView.setNavigationItemSelectedListener { menuItem : MenuItem ->
|
navigationView.setNavigationItemSelectedListener { menuItem : MenuItem ->
|
||||||
when(menuItem.itemId) {
|
when(menuItem.itemId) {
|
||||||
R.id.menu_kotlin_activity -> {
|
R.id.menu_kotlin_fragment -> {
|
||||||
if (selected != 0) {
|
if (selected != 0) {
|
||||||
supportFragmentManager.beginTransaction().apply {
|
supportFragmentManager.beginTransaction().apply {
|
||||||
replace(R.id.fragment_container, KotlinFragment.newInstance())
|
replace(R.id.fragment_container, KotlinFragment.newInstance())
|
||||||
|
@ -48,7 +51,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
selected = 0
|
selected = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.menu_java_activity -> {
|
R.id.menu_java_fragment -> {
|
||||||
if (selected != 1) {
|
if (selected != 1) {
|
||||||
supportFragmentManager.beginTransaction().apply {
|
supportFragmentManager.beginTransaction().apply {
|
||||||
replace(R.id.fragment_container, JavaFragment())
|
replace(R.id.fragment_container, JavaFragment())
|
||||||
|
@ -57,6 +60,15 @@ class MainActivity : AppCompatActivity() {
|
||||||
selected = 1
|
selected = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
R.id.menu_apng_decoder_fragment -> {
|
||||||
|
if (selected != 2) {
|
||||||
|
supportFragmentManager.beginTransaction().apply {
|
||||||
|
replace(R.id.fragment_container, ApngDecoderFragment.newInstance())
|
||||||
|
addToBackStack(null)
|
||||||
|
}.commit()
|
||||||
|
selected = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer_layout.closeDrawer(GravityCompat.START)
|
drawer_layout.closeDrawer(GravityCompat.START)
|
||||||
|
@ -64,12 +76,36 @@ class MainActivity : AppCompatActivity() {
|
||||||
return@setNavigationItemSelectedListener true
|
return@setNavigationItemSelectedListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
supportFragmentManager.beginTransaction().apply {
|
if (intent.hasExtra("fragment")) {
|
||||||
add(R.id.fragment_container, KotlinFragment.newInstance(), "KotlinFragment")
|
when(intent.getStringExtra("fragment")) {
|
||||||
}.commit()
|
"kotlin" -> {
|
||||||
|
supportFragmentManager.beginTransaction().apply {
|
||||||
|
add(R.id.fragment_container, KotlinFragment.newInstance(), "KotlinFragment")
|
||||||
navigationView.setCheckedItem(R.id.menu_kotlin_activity)
|
}.commit()
|
||||||
|
navigationView.setCheckedItem(R.id.menu_kotlin_fragment)
|
||||||
|
selected = 0
|
||||||
|
}
|
||||||
|
"java" -> {
|
||||||
|
supportFragmentManager.beginTransaction().apply {
|
||||||
|
add(R.id.fragment_container, JavaFragment())
|
||||||
|
}.commit()
|
||||||
|
navigationView.setCheckedItem(R.id.menu_java_fragment)
|
||||||
|
selected = 1
|
||||||
|
}
|
||||||
|
"apng_decoder" -> {
|
||||||
|
supportFragmentManager.beginTransaction().apply {
|
||||||
|
add(R.id.fragment_container, ApngDecoderFragment.newInstance())
|
||||||
|
}.commit()
|
||||||
|
navigationView.setCheckedItem(R.id.menu_apng_decoder_fragment)
|
||||||
|
selected = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
supportFragmentManager.beginTransaction().apply {
|
||||||
|
add(R.id.fragment_container, KotlinFragment.newInstance(), "KotlinFragment")
|
||||||
|
}.commit()
|
||||||
|
navigationView.setCheckedItem(R.id.menu_kotlin_fragment)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpBottomAppBarShapeAppearance() {
|
private fun setUpBottomAppBarShapeAppearance() {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout 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=".ApngDecoderFragment">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/apngDecoderImageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:contentDescription="@string/description_viewer_imageView"/>
|
||||||
|
</FrameLayout>
|
|
@ -2,12 +2,16 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<group android:checkableBehavior="single">
|
<group android:checkableBehavior="single">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_kotlin_activity"
|
android:id="@+id/menu_kotlin_fragment"
|
||||||
android:icon="@drawable/ic_kotlin"
|
android:icon="@drawable/ic_kotlin"
|
||||||
android:title="@string/menu_title_kotlin_activity" />
|
android:title="@string/menu_title_kotlin_fragment" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_java_activity"
|
android:id="@+id/menu_java_fragment"
|
||||||
android:icon="@drawable/ic_java"
|
android:icon="@drawable/ic_java"
|
||||||
android:title="@string/menu_title_java_activity" />
|
android:title="@string/menu_title_java_fragment" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_apng_decoder_fragment"
|
||||||
|
android:title="@string/menu_title_apng_decoder_fragment" />
|
||||||
</group>
|
</group>
|
||||||
</menu>
|
</menu>
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<color name="gray">#999999</color>
|
<color name="gray">#999999</color>
|
||||||
|
|
||||||
<color name="background">#ffffff</color>
|
<color name="background">#FFFFFF</color>
|
||||||
|
|
||||||
<color name="control">#fff</color>
|
<color name="control">#fff</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -10,8 +10,9 @@
|
||||||
<string name="title_playButton">Play</string>
|
<string name="title_playButton">Play</string>
|
||||||
<string name="title_pauseButton">Pause</string>
|
<string name="title_pauseButton">Pause</string>
|
||||||
|
|
||||||
<string name="menu_title_kotlin_activity">Kotlin Activity</string>
|
<string name="menu_title_kotlin_fragment">Kotlin Fragment</string>
|
||||||
<string name="menu_title_java_activity">Java Activity</string>
|
<string name="menu_title_java_fragment">Java Fragment</string>
|
||||||
|
<string name="menu_title_apng_decoder_fragment">ApngDecoder</string>
|
||||||
|
|
||||||
<string name="create">Create</string>
|
<string name="create">Create</string>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue