diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
index 60a7e8e..abf6a95 100644
--- a/.idea/assetWizardSettings.xml
+++ b/.idea/assetWizardSettings.xml
@@ -18,7 +18,7 @@
@@ -29,8 +29,8 @@
diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
index 52a3bf1..746bc38 100644
Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ
diff --git a/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt b/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt
index 868fa02..2404c77 100644
--- a/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt
+++ b/apng_library/src/main/java/oupson/apng/APNGDisassembler.kt
@@ -128,8 +128,9 @@ class APNGDisassembler {
val crc = CRC32()
crc.update(byteArray.copyOfRange(i, byteArray.size - 4))
if (chunkCRC == crc.value.toInt()) {
- when (byteArray.copyOfRange(i, i + 4).contentToString()) {
- Utils.fcTL -> {
+ val name= byteArray.copyOfRange(i, i + 4)
+ when {
+ name.contentEquals(Utils.fcTL) -> {
if (png == null) {
cover?.let {
it.addAll(to4Bytes(0).asList())
@@ -198,7 +199,7 @@ class APNGDisassembler {
}
}
}
- Utils.IEND -> {
+ name.contentEquals(Utils.IEND) -> {
if (isApng) {
png?.addAll(to4Bytes(0).asList())
// Add IEND
@@ -235,7 +236,7 @@ class APNGDisassembler {
apng.isApng = false
}
}
- Utils.IDAT -> {
+ name.contentEquals(Utils.IDAT) -> {
if (png == null) {
if (cover == null) {
cover = ArrayList()
@@ -267,7 +268,7 @@ class APNGDisassembler {
png?.addAll(to4Bytes(crC32.value.toInt()).asList())
}
}
- Utils.fdAT -> {
+ name.contentEquals(Utils.fdAT) -> {
// Find the chunk length
val bodySize = parseLength(byteArray.copyOfRange(i - 4, i))
png?.addAll(to4Bytes(bodySize - 4).asList())
@@ -280,18 +281,18 @@ class APNGDisassembler {
png?.addAll(body)
png?.addAll(to4Bytes(crC32.value.toInt()).asList())
}
- Utils.plte -> {
+ name.contentEquals(Utils.plte) -> {
plte = byteArray
}
- Utils.tnrs -> {
+ name.contentEquals(Utils.tnrs) -> {
tnrs = byteArray
}
- Utils.IHDR -> {
+ name.contentEquals(Utils.IHDR) -> {
ihdr.parse(byteArray)
maxWidth = ihdr.pngWidth
maxHeight = ihdr.pngHeight
}
- Utils.acTL -> {
+ name.contentEquals(Utils.acTL) -> {
isApng = true
}
}
diff --git a/apng_library/src/main/java/oupson/apng/ExperimentalApngDecoder.kt b/apng_library/src/main/java/oupson/apng/ExperimentalApngDecoder.kt
index 01f9460..a53aa1f 100644
--- a/apng_library/src/main/java/oupson/apng/ExperimentalApngDecoder.kt
+++ b/apng_library/src/main/java/oupson/apng/ExperimentalApngDecoder.kt
@@ -41,6 +41,7 @@ class ExperimentalApngDecoder {
* @param speed Optional parameter.
*/
@Suppress("MemberVisibilityCanBePrivate")
+ @JvmStatic
fun decodeApng(inStream: InputStream, speed : Float = 1f) : Drawable {
val inputStream = BufferedInputStream(inStream)
val bytes = ByteArray(8)
@@ -85,8 +86,9 @@ class ExperimentalApngDecoder {
val crc = CRC32()
crc.update(byteArray.copyOfRange(i, byteArray.size - 4))
if (chunkCRC == crc.value.toInt()) {
- when (byteArray.copyOfRange(i, i + 4).contentToString()) {
- Utils.fcTL -> {
+ val name = byteArray.copyOfRange(i, i + 4)
+ when {
+ name.contentEquals(Utils.fcTL) -> {
if (png == null) {
cover?.let {
it.addAll(Utils.to4Bytes(0).asList())
@@ -184,7 +186,7 @@ class ExperimentalApngDecoder {
}
}
}
- Utils.IEND -> {
+ name.contentEquals(Utils.IEND) -> {
if (isApng && png != null) {
png.addAll(Utils.to4Bytes(0).asList())
// Add IEND
@@ -239,7 +241,7 @@ class ExperimentalApngDecoder {
}
}
}
- Utils.IDAT -> {
+ name.contentEquals(Utils.IDAT) -> {
if (png == null) {
if (cover == null) {
cover = ArrayList()
@@ -275,7 +277,7 @@ class ExperimentalApngDecoder {
png.addAll(Utils.to4Bytes(crC32.value.toInt()).asList())
}
}
- Utils.fdAT -> {
+ name.contentEquals(Utils.fdAT) -> {
// Find the chunk length
val bodySize = Utils.parseLength(byteArray.copyOfRange(i - 4, i))
png?.addAll(Utils.to4Bytes(bodySize - 4).asList())
@@ -288,19 +290,19 @@ class ExperimentalApngDecoder {
png?.addAll(body)
png?.addAll(Utils.to4Bytes(crC32.value.toInt()).asList())
}
- Utils.plte -> {
+ name.contentEquals(Utils.plte) -> {
plte = byteArray
}
- Utils.tnrs -> {
+ name.contentEquals(Utils.tnrs) -> {
tnrs = byteArray
}
- Utils.IHDR -> {
+ name.contentEquals(Utils.IHDR) -> {
ihdr.parse(byteArray)
maxWidth = ihdr.pngWidth
maxHeight =ihdr.pngHeight
buffer = Bitmap.createBitmap(maxWidth, maxHeight, Bitmap.Config.ARGB_8888)
}
- Utils.acTL -> {
+ name.contentEquals(Utils.acTL) -> {
isApng = true
}
}
@@ -325,6 +327,7 @@ class ExperimentalApngDecoder {
* @param speed Optional parameter.
*/
@Suppress("unused")
+ @JvmStatic
fun decodeApng(file : File, speed: Float = 1f) : Drawable = decodeApng(FileInputStream(file), speed)
/**
@@ -333,6 +336,7 @@ class ExperimentalApngDecoder {
* @param uri Uri to open.
* @param speed Optional parameter.
*/
+ @JvmStatic
fun decodeApng(context : Context, uri : Uri, speed: Float = 1f) : Drawable {
val inputStream = context.contentResolver.openInputStream(uri)
?: throw Exception("Failed to open InputStream, InputStream is null")
@@ -346,6 +350,7 @@ class ExperimentalApngDecoder {
* @param speed Optional parameter.
*/
@Suppress("unused")
+ @JvmStatic
fun decodeApng(context : Context, @RawRes res : Int, speed: Float = 1f) : Drawable = decodeApng(context.resources.openRawResource(res), speed)
/**
@@ -354,6 +359,8 @@ class ExperimentalApngDecoder {
* @param url URL to decode.
* @param speed Optional parameter.
*/
+ @Suppress("unused")
+ @JvmStatic
suspend fun decodeApng(context : Context, url : URL, speed: Float = 1f) = withContext(Dispatchers.IO) {
decodeApng(FileInputStream(Loader.load(context, url)), speed)
}
diff --git a/apng_library/src/main/java/oupson/apng/Frame.kt b/apng_library/src/main/java/oupson/apng/Frame.kt
index 643d44a..bb11a5a 100644
--- a/apng_library/src/main/java/oupson/apng/Frame.kt
+++ b/apng_library/src/main/java/oupson/apng/Frame.kt
@@ -81,18 +81,16 @@ class Frame// Get width and height for image
* @param byteArray The frame
*/
private fun parseChunk(byteArray: ByteArray) {
- when(byteArray.copyOfRange(4, 8).contentToString()) {
- IHDR -> {
- ihdr = IHDR()
- ihdr.parse(byteArray)
- width = ihdr.pngWidth
- height = ihdr.pngHeight
- }
- IDAT -> {
- // Get IDAT Bytes
- idat = IDAT()
- idat.parse(byteArray)
- }
+ val name = byteArray.copyOfRange(4, 8)
+ if (name.contentEquals(IHDR)) {
+ ihdr = IHDR()
+ ihdr.parse(byteArray)
+ width = ihdr.pngWidth
+ height = ihdr.pngHeight
+ } else if (name.contentEquals(IDAT)){
+ // Get IDAT Bytes
+ idat = IDAT()
+ idat.parse(byteArray)
}
}
}
\ No newline at end of file
diff --git a/apng_library/src/main/java/oupson/apng/Loader.kt b/apng_library/src/main/java/oupson/apng/Loader.kt
index 587b35e..be2e3f6 100644
--- a/apng_library/src/main/java/oupson/apng/Loader.kt
+++ b/apng_library/src/main/java/oupson/apng/Loader.kt
@@ -16,7 +16,6 @@ class Loader {
* @param url Url of the file to download
* @return [ByteArray] of the file
*/
- @Suppress("RedundantSuspendModifier")
@Throws(IOException::class)
suspend fun load(context: Context, url: URL): File = withContext(Dispatchers.IO) {
val currentDir = context.filesDir
diff --git a/apng_library/src/main/java/oupson/apng/utils/Utils.kt b/apng_library/src/main/java/oupson/apng/utils/Utils.kt
index 8ec1d62..d1af031 100644
--- a/apng_library/src/main/java/oupson/apng/utils/Utils.kt
+++ b/apng_library/src/main/java/oupson/apng/utils/Utils.kt
@@ -7,7 +7,11 @@ class Utils {
* @return [Boolean] True if is a png
*/
fun isPng(byteArray: ByteArray): Boolean {
- return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
+ // return byteArray.copyOfRange(0, 8).contentToString() == pngSignature.contentToString()
+ return if (byteArray.size == 8)
+ byteArray.contentEquals(pngSignature)
+ else
+ byteArray.copyOfRange(0, 8).contentEquals(pngSignature)
}
/**
@@ -146,13 +150,13 @@ class Utils {
return lengthString.toLong(16).toInt()
}
- val fcTL : String by lazy { byteArrayOf(0x66, 0x63, 0x54, 0x4c).contentToString() }
- val IEND : String by lazy { byteArrayOf(0x49, 0x45, 0x4e, 0x44).contentToString() }
- val IDAT : String by lazy { byteArrayOf(0x49, 0x44, 0x41, 0x54).contentToString() }
- val fdAT : String by lazy { byteArrayOf(0x66, 0x64, 0x41, 0x54).contentToString() }
- val plte : String by lazy { byteArrayOf(0x50, 0x4c, 0x54, 0x45).contentToString() }
- val tnrs : String by lazy { byteArrayOf(0x74, 0x52, 0x4e, 0x53).contentToString() }
- val IHDR : String by lazy { byteArrayOf(0x49, 0x48, 0x44, 0x52).contentToString() }
- val acTL : String by lazy { byteArrayOf(0x61, 0x63, 0x54, 0x4c).contentToString() }
+ val fcTL : ByteArray by lazy { byteArrayOf(0x66, 0x63, 0x54, 0x4c) }
+ val IEND : ByteArray by lazy { byteArrayOf(0x49, 0x45, 0x4e, 0x44) }
+ val IDAT : ByteArray by lazy { byteArrayOf(0x49, 0x44, 0x41, 0x54) }
+ val fdAT : ByteArray by lazy { byteArrayOf(0x66, 0x64, 0x41, 0x54) }
+ val plte : ByteArray by lazy { byteArrayOf(0x50, 0x4c, 0x54, 0x45) }
+ val tnrs : ByteArray by lazy { byteArrayOf(0x74, 0x52, 0x4e, 0x53) }
+ val IHDR : ByteArray by lazy { byteArrayOf(0x49, 0x48, 0x44, 0x52) }
+ val acTL : ByteArray by lazy { byteArrayOf(0x61, 0x63, 0x54, 0x4c) }
}
}
\ No newline at end of file
diff --git a/app-test/build.gradle b/app-test/build.gradle
index bca1e56..706c1eb 100644
--- a/app-test/build.gradle
+++ b/app-test/build.gradle
@@ -36,6 +36,7 @@ dependencies {
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
@@ -44,7 +45,7 @@ dependencies {
implementation project(":apng_library")
// implementation fileTree(include: ['*.aar'], dir: 'libs')
//implementation 'com.github.oupson:Kapng-Android:1.0.0'
- implementation 'com.google.android.material:material:1.0.0'
+ implementation 'com.google.android.material:material:1.2.0-alpha04'
implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
implementation "org.jetbrains.anko:anko-design:$anko_version"
implementation "org.jetbrains.anko:anko-constraint-layout:$anko_version"
diff --git a/app-test/src/main/AndroidManifest.xml b/app-test/src/main/AndroidManifest.xml
index bc76a72..b6115e5 100644
--- a/app-test/src/main/AndroidManifest.xml
+++ b/app-test/src/main/AndroidManifest.xml
@@ -16,9 +16,6 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
-
-
@@ -27,7 +24,7 @@
diff --git a/app-test/src/main/java/oupson/apngcreator/CreatorActivity.kt b/app-test/src/main/java/oupson/apngcreator/CreatorActivity.kt
index ee0a25d..8beb3be 100644
--- a/app-test/src/main/java/oupson/apngcreator/CreatorActivity.kt
+++ b/app-test/src/main/java/oupson/apngcreator/CreatorActivity.kt
@@ -23,6 +23,7 @@ import oupson.apng.ApngAnimator
import oupson.apngcreator.adapter.AnkoAdapter
import java.io.File
+// TODO
class CreatorActivity : AppCompatActivity() {
companion object {
private const val PICK_IMAGE = 999
@@ -112,11 +113,11 @@ class CreatorActivity : AppCompatActivity() {
}
class CreatorActivityLayout : AnkoComponent {
- lateinit var listView : ListView
- lateinit var addFrameButton : FloatingActionButton
- lateinit var createButton : FloatingActionButton
- lateinit var optimiseCheckBox : CheckBox
- lateinit var toolbar : Toolbar
+ lateinit var listView: ListView
+ lateinit var addFrameButton: FloatingActionButton
+ lateinit var createButton: FloatingActionButton
+ lateinit var optimiseCheckBox: CheckBox
+ lateinit var toolbar: Toolbar
override fun createView(ui: AnkoContext) = with(ui) {
relativeLayout {
backgroundColor = Color.WHITE
@@ -124,57 +125,58 @@ class CreatorActivityLayout : AnkoComponent {
id = View.generateViewId()
backgroundColor = Color.WHITE
appBarLayout {
- toolbar = xToolbar {
- id = View.generateViewId()
+ /**toolbar = xToolbar {
+ id = View.generateViewId()
}.lparams {
- width = matchParent
- height = wrapContent
+ width = matchParent
+ height = wrapContent
}
- }.lparams {
+ }.lparams {
width = matchParent
height = wrapContent
bottomMargin = 1
+ }*/
+ }.lparams {
+ width = matchParent
+ height = wrapContent
+ }
+ optimiseCheckBox = checkBox("Optimise APNG, WIP !") {
+ id = View.generateViewId()
+ }.lparams {
+ width = matchParent
+ //below(bar)
+ }
+ listView = listView {
+ id = View.generateViewId()
+ }.lparams {
+ width = matchParent
+ height = matchParent
+ //below(optimiseCheckBox)
+ }
+ addFrameButton = floatingActionButton {
+ imageResource = R.drawable.ic_add_black_24dp
+ imageTintList = ColorStateList.valueOf(Color.WHITE)
+ backgroundTintList = ColorStateList.valueOf(Color.BLACK)
+ isClickable = true
+ }.lparams {
+ width = wrapContent
+ height = wrapContent
+ margin = dip(5)
+ //alignParentBottom()
+ //alignParentEnd()
+ }
+ createButton = floatingActionButton {
+ imageResource = R.drawable.ic_play_arrow_black_24dp
+ imageTintList = ColorStateList.valueOf(Color.WHITE)
+ backgroundTintList = ColorStateList.valueOf(Color.BLACK)
+ isClickable = true
+ }.lparams {
+ width = wrapContent
+ height = wrapContent
+ margin = dip(5)
+ //alignParentBottom()
+ //alignParentStart()
}
- }.lparams {
- width = matchParent
- height = wrapContent
- }
- optimiseCheckBox = checkBox("Optimise APNG, WIP !") {
- id = View.generateViewId()
- }.lparams {
- width = matchParent
- below(bar)
- }
- listView = listView {
- id = View.generateViewId()
- }.lparams {
- width = matchParent
- height = matchParent
- below(optimiseCheckBox)
- }
- addFrameButton = floatingActionButton {
- imageResource = R.drawable.ic_add_black_24dp
- imageTintList = ColorStateList.valueOf(Color.WHITE)
- backgroundTintList = ColorStateList.valueOf(Color.BLACK)
- isClickable = true
- }.lparams {
- width = wrapContent
- height = wrapContent
- margin = dip(5)
- alignParentBottom()
- alignParentEnd()
- }
- createButton = floatingActionButton {
- imageResource = R.drawable.ic_play_arrow_black_24dp
- imageTintList = ColorStateList.valueOf(Color.WHITE)
- backgroundTintList = ColorStateList.valueOf(Color.BLACK)
- isClickable = true
- }.lparams {
- width = wrapContent
- height = wrapContent
- margin = dip(5)
- alignParentBottom()
- alignParentStart()
}
}
}
diff --git a/app-test/src/main/java/oupson/apngcreator/JavaActivity.java b/app-test/src/main/java/oupson/apngcreator/JavaActivity.java
deleted file mode 100644
index ed91b44..0000000
--- a/app-test/src/main/java/oupson/apngcreator/JavaActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package oupson.apngcreator;
-
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.ImageView;
-import androidx.appcompat.app.AppCompatActivity;
-import kotlin.Unit;
-import oupson.apng.ApngAnimator;
-import oupson.apng.ApngAnimatorKt;
-public class JavaActivity extends AppCompatActivity {
- private static final String TAG = "JavaActivity";
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_java);
- String imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png";
- ImageView image = findViewById(R.id.javaImageView);
- ApngAnimator a = ApngAnimatorKt.loadApng(image, imageUrl);
- a.onLoaded((animator) -> {
- animator.setOnFrameChangeLister((index) -> {
- if (index == 0) {
- Log.i(TAG, "Loop");
- }
- return Unit.INSTANCE;
- });
- return Unit.INSTANCE;
- });
-
- }
-}
diff --git a/app-test/src/main/java/oupson/apngcreator/JavaFragment.java b/app-test/src/main/java/oupson/apngcreator/JavaFragment.java
new file mode 100644
index 0000000..76fe2d3
--- /dev/null
+++ b/app-test/src/main/java/oupson/apngcreator/JavaFragment.java
@@ -0,0 +1,43 @@
+package oupson.apngcreator;
+
+
+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 kotlin.Unit;
+import oupson.apng.ApngAnimator;
+import oupson.apng.ApngAnimatorKt;
+
+
+public class JavaFragment extends Fragment {
+ private static final String TAG = "JavaActivity";
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ Log.i(TAG, "onCreateView()");
+ View v = inflater.inflate(R.layout.fragment_java, container, false);
+ String imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png";
+ ImageView imageView = v.findViewById(R.id.javaImageView);
+ if (imageView != null) {
+ ApngAnimator a = ApngAnimatorKt.loadApng(imageView, imageUrl);
+ a.onLoaded((animator) -> {
+ animator.setOnFrameChangeLister((index) -> {
+ if (index == 0) {
+ Log.i(TAG, "Loop");
+ }
+ return Unit.INSTANCE;
+ });
+ return Unit.INSTANCE;
+ });
+ }
+ return v;
+ }
+
+}
diff --git a/app-test/src/main/java/oupson/apngcreator/KotlinFragment.kt b/app-test/src/main/java/oupson/apngcreator/KotlinFragment.kt
new file mode 100644
index 0000000..1ae692d
--- /dev/null
+++ b/app-test/src/main/java/oupson/apngcreator/KotlinFragment.kt
@@ -0,0 +1,120 @@
+package oupson.apngcreator
+
+
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.SeekBar
+import androidx.fragment.app.Fragment
+import com.squareup.picasso.Picasso
+import oupson.apng.ApngAnimator
+import oupson.apng.loadApng
+
+
+class KotlinFragment : Fragment() {
+ private var apngImageView : ImageView? = null
+ private var normalImageView : ImageView? = null
+
+ private var pauseButton : Button? = null
+ private var playButton : Button? = null
+
+ private var speedSeekBar : SeekBar? = null
+
+ private var animator : ApngAnimator? = null
+
+ private val imageUrls = arrayListOf(
+ "http://oupson.oupsman.fr/apng/bigApng.png",
+ "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png",
+ "https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg",
+ "http://orig06.deviantart.net/7812/f/2012/233/7/5/twilight_rapidash_shaded_and_animated_by_tamalesyatole-d5bz7hd.png",
+ "https://raw.githubusercontent.com/tinify/iMessage-Panda-sticker/master/StickerPackExtension/Stickers.xcstickers/Sticker%20Pack.stickerpack/panda.sticker/panda.png",
+ "file:///android_asset/image.png"
+ )
+ private val selected = 4
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, "onCreateView()")
+ // Inflate the layout for this fragment
+ val view = inflater.inflate(R.layout.fragment_kotlin, container, false)
+
+ apngImageView = view.findViewById(R.id.ApngImageView)
+ normalImageView = view.findViewById(R.id.NormalImageView)
+
+ pauseButton = view.findViewById(R.id.PauseButton)
+ playButton = view.findViewById(R.id.PlayButton)
+
+ speedSeekBar = view.findViewById(R.id.SpeedSeekBar)
+
+ return view
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, "onResume()")
+
+ playButton?.setOnClickListener {
+ animator?.play()
+ }
+
+ pauseButton?.setOnClickListener {
+ animator?.pause()
+ }
+
+ speedSeekBar?.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar?) {
+
+ }
+
+ override fun onStopTrackingTouch(seekBar: SeekBar?) {
+ if (seekBar != null)
+ animator?.speed = seekBar.progress.toFloat() / 100f
+ }
+ })
+
+ if (animator == null) {
+ animator = apngImageView?.loadApng(imageUrls[selected])?.apply {
+ onLoaded {
+ setOnFrameChangeLister {
+ // Log.e("app-test", "onLoop")
+ }
+ }
+ }
+ }
+
+ Picasso.get().load(imageUrls[selected]).into(normalImageView)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ if (BuildConfig.DEBUG)
+ Log.i(TAG, "onPause()")
+
+ // animator = null
+ normalImageView?.setImageDrawable(null)
+ // apngImageView?.setImageDrawable(null)
+
+ playButton?.setOnClickListener(null)
+ pauseButton?.setOnClickListener(null)
+ speedSeekBar?.setOnSeekBarChangeListener(null)
+ }
+
+ companion object {
+ private const val TAG = "KotlinFragment"
+ @JvmStatic
+ fun newInstance() =
+ KotlinFragment()
+ }
+}
\ No newline at end of file
diff --git a/app-test/src/main/java/oupson/apngcreator/MainActivity.kt b/app-test/src/main/java/oupson/apngcreator/MainActivity.kt
index ff2426a..71bb185 100644
--- a/app-test/src/main/java/oupson/apngcreator/MainActivity.kt
+++ b/app-test/src/main/java/oupson/apngcreator/MainActivity.kt
@@ -1,188 +1,131 @@
package oupson.apngcreator
-import android.graphics.Color
+import android.annotation.SuppressLint
import android.os.Bundle
-import android.view.Menu
import android.view.MenuItem
-import android.view.View
-import android.view.ViewManager
+import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
-import androidx.constraintlayout.widget.ConstraintLayout
-import com.squareup.picasso.Picasso
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import org.jetbrains.anko.*
-import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder
-import org.jetbrains.anko.constraint.layout.applyConstraintSet
-import org.jetbrains.anko.constraint.layout.constraintLayout
-import org.jetbrains.anko.constraint.layout.matchConstraint
-import org.jetbrains.anko.custom.ankoView
-import org.jetbrains.anko.design.appBarLayout
-import org.jetbrains.anko.sdk27.coroutines.onClick
-import org.jetbrains.anko.sdk27.coroutines.onSeekBarChangeListener
-import oupson.apng.ApngAnimator
-import oupson.apng.CustomAnimationDrawable
-import oupson.apng.ExperimentalApngDecoder
-import java.net.URL
+import androidx.core.view.GravityCompat
+import com.google.android.material.bottomappbar.BottomAppBarTopEdgeTreatment
+import com.google.android.material.shape.CutCornerTreatment
+import com.google.android.material.shape.MaterialShapeDrawable
+import com.google.android.material.shape.ShapeAppearanceModel
+import com.google.android.material.shape.ShapePath
+import kotlinx.android.synthetic.main.activity_main.*
+import org.jetbrains.anko.startActivity
+
-// TODO REMOVE ANKO
-fun ViewManager.xToolbar(init : androidx.appcompat.widget.Toolbar.() -> Unit) = ankoView({androidx.appcompat.widget.Toolbar(it)}, 0, init)
class MainActivity : AppCompatActivity() {
- private lateinit var animator: ApngAnimator
- private lateinit var tool : androidx.appcompat.widget.Toolbar
- // val imageUrl = "http://oupson.oupsman.fr/apng/bigApng.png"
- private val imageUrl = "https://metagif.files.wordpress.com/2015/01/bugbuckbunny.png"
- //private val imageUrl = "https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg"
- // val imageUrl = "http://orig06.deviantart.net/7812/f/2012/233/7/5/twilight_rapidash_shaded_and_animated_by_tamalesyatole-d5bz7hd.png"
- // val imageUrl = "https://raw.githubusercontent.com/tinify/iMessage-Panda-sticker/master/StickerPackExtension/Stickers.xcstickers/Sticker%20Pack.stickerpack/panda.sticker/panda.png"
- // val imageUrl = "file:///android_asset/image.png"
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- verticalLayout {
- verticalLayout {
- appBarLayout {
- tool = xToolbar {
- id = View.generateViewId()
- }.lparams {
- width = matchParent
- height = wrapContent
- }
- }.lparams {
- width = matchParent
- height = wrapContent
- bottomMargin = 1
- }
- }.lparams {
- width = matchParent
- height = wrapContent
- }
- constraintLayout {
- backgroundColor = Color.WHITE
- val pauseButton = button("pause") {
- backgroundColor = Color.WHITE
- id = View.generateViewId()
- onClick {
- animator.pause()
- }
- }.lparams(
- width = wrapContent,
- height = wrapContent
- )
- val playButton = button("play") {
- backgroundColor = Color.WHITE
- id = View.generateViewId()
- onClick {
- animator.play()
- }
- }.lparams(
- width = wrapContent,
- height = wrapContent
- )
- val seekBar = seekBar {
- id = View.generateViewId()
- max = 200
- progress = 100
- onSeekBarChangeListener {
- onProgressChanged { _, _, _ -> }
- onStartTrackingTouch { }
- onStopTrackingTouch { seekBar ->
- animator.speed = (seekBar?.progress?.toFloat() ?: 100f) / 100f
- }
- }
- }.lparams(
- width = matchConstraint,
- height = wrapContent
- )
- val imageView2 = imageView {
- id = View.generateViewId()
- Picasso.get().load(imageUrl).into(this)
- }.lparams(
- width = matchConstraint,
- height = matchConstraint
- )
- val imageView = imageView {
- id = View.generateViewId()
- GlobalScope.launch(Dispatchers.IO) {
- val drawable = ExperimentalApngDecoder.decodeApng(this@MainActivity, URL(imageUrl))
- GlobalScope.launch(Dispatchers.Main) {
- this@imageView.setImageDrawable(drawable)
- if (drawable is CustomAnimationDrawable)
- drawable.start()
- }
- }
+ setContentView(R.layout.activity_main)
- /**
- animator = this.loadApng(imageUrl).apply {
- onLoaded {
- setOnFrameChangeLister {
- // Log.e("app-test", "onLoop")
- }
- }
- }
- */
- }.lparams(
- width = matchConstraint,
- height = matchConstraint
- )
- applyConstraintSet {
- pauseButton {
- connect(
- ConstraintSetBuilder.Side.BOTTOM to ConstraintSetBuilder.Side.TOP of seekBar margin dip(8),
- ConstraintSetBuilder.Side.END to ConstraintSetBuilder.Side.END of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8)
- )
- }
- playButton {
- connect(
- ConstraintSetBuilder.Side.BOTTOM to ConstraintSetBuilder.Side.TOP of seekBar margin dip(8),
- ConstraintSetBuilder.Side.START to ConstraintSetBuilder.Side.START of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8)
- )
- }
- seekBar {
- connect(
- ConstraintSetBuilder.Side.BOTTOM to ConstraintSetBuilder.Side.BOTTOM of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.END to ConstraintSetBuilder.Side.END of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.START to ConstraintSetBuilder.Side.START of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8)
- )
- }
- imageView2 {
- connect(
- ConstraintSetBuilder.Side.BOTTOM to ConstraintSetBuilder.Side.TOP of playButton margin dip(8),
- ConstraintSetBuilder.Side.END to ConstraintSetBuilder.Side.END of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.START to ConstraintSetBuilder.Side.START of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.TOP to ConstraintSetBuilder.Side.BOTTOM of imageView
- )
- }
- imageView {
- connect(
- ConstraintSetBuilder.Side.BOTTOM to ConstraintSetBuilder.Side.TOP of imageView2 margin dip(8),
- ConstraintSetBuilder.Side.END to ConstraintSetBuilder.Side.END of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.START to ConstraintSetBuilder.Side.START of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8),
- ConstraintSetBuilder.Side.TOP to ConstraintSetBuilder.Side.TOP of ConstraintLayout.LayoutParams.PARENT_ID margin dip(8)
- )
+ setSupportActionBar(bottomAppBar)
+
+ setUpBottomAppBarShapeAppearance()
+
+ fabCreate.setOnClickListener {
+ startActivity()
+ }
+
+ val drawerToggle = ActionBarDrawerToggle(this, drawer_layout, bottomAppBar, R.string.open, R.string.close)
+ drawer_layout.addDrawerListener(drawerToggle)
+ drawerToggle.syncState()
+
+ var selected = 0
+
+ navigationView.setNavigationItemSelectedListener { menuItem : MenuItem ->
+ when(menuItem.itemId) {
+ R.id.menu_kotlin_activity -> {
+ if (selected != 0) {
+ supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, KotlinFragment.newInstance())
+ addToBackStack(null)
+ }.commit()
+ selected = 0
+ }
+ }
+ R.id.menu_java_activity -> {
+ if (selected != 1) {
+ supportFragmentManager.beginTransaction().apply {
+ replace(R.id.fragment_container, JavaFragment())
+ addToBackStack(null)
+ }.commit()
+ selected = 1
}
}
- }.lparams {
- width = matchParent
- height = matchParent
}
+
+ drawer_layout.closeDrawer(GravityCompat.START)
+
+ return@setNavigationItemSelectedListener true
}
- setSupportActionBar(tool)
+
+ supportFragmentManager.beginTransaction().apply {
+ add(R.id.fragment_container, KotlinFragment.newInstance(), "KotlinFragment")
+ }.commit()
+
+
+ navigationView.setCheckedItem(R.id.menu_kotlin_activity)
}
- override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- val inflater = menuInflater
- inflater.inflate(R.menu.main_menu, menu)
- return true
+ private fun setUpBottomAppBarShapeAppearance() {
+ val fabShapeAppearanceModel: ShapeAppearanceModel = fabCreate.shapeAppearanceModel
+ val cutCornersFab =
+ (fabShapeAppearanceModel.bottomLeftCorner is CutCornerTreatment
+ && fabShapeAppearanceModel.bottomRightCorner is CutCornerTreatment)
+ val topEdge =
+ if (cutCornersFab) BottomAppBarCutCornersTopEdge(
+ bottomAppBar.fabCradleMargin,
+ bottomAppBar.fabCradleRoundedCornerRadius,
+ bottomAppBar.cradleVerticalOffset
+ ) else BottomAppBarTopEdgeTreatment(
+ bottomAppBar.fabCradleMargin,
+ bottomAppBar.fabCradleRoundedCornerRadius,
+ bottomAppBar.cradleVerticalOffset
+ )
+ val babBackground = bottomAppBar.background as MaterialShapeDrawable
+ babBackground.shapeAppearanceModel =
+ babBackground.shapeAppearanceModel.toBuilder().setTopEdge(topEdge).build()
}
- override fun onOptionsItemSelected(item: MenuItem?): Boolean {
- when (item!!.itemId) {
- R.id.action_open_create_activity -> startActivity()
- R.id.action_open_java_activity -> startActivity()
+
+ inner class BottomAppBarCutCornersTopEdge(
+ private val fabMargin: Float,
+ roundedCornerRadius: Float,
+ private val cradleVerticalOffset: Float
+ ) :
+ BottomAppBarTopEdgeTreatment(fabMargin, roundedCornerRadius, cradleVerticalOffset) {
+ @SuppressLint("RestrictedApi")
+ override fun getEdgePath(
+ length: Float,
+ center: Float,
+ interpolation: Float,
+ shapePath: ShapePath
+ ) {
+ val fabDiameter = fabDiameter
+ if (fabDiameter == 0f) {
+ shapePath.lineTo(length, 0f)
+ return
+ }
+ val diamondSize = fabDiameter / 2f
+ val middle = center + horizontalOffset
+ val verticalOffsetRatio = cradleVerticalOffset / diamondSize
+ if (verticalOffsetRatio >= 1.0f) {
+ shapePath.lineTo(length, 0f)
+ return
+ }
+ shapePath.lineTo(middle - (fabMargin + diamondSize - cradleVerticalOffset), 0f)
+ shapePath.lineTo(
+ middle,
+ (diamondSize - cradleVerticalOffset + fabMargin) * interpolation
+ )
+ shapePath.lineTo(middle + (fabMargin + diamondSize - cradleVerticalOffset), 0f)
+ shapePath.lineTo(length, 0f)
}
- return super.onOptionsItemSelected(item)
+
}
}
diff --git a/app-test/src/main/java/oupson/apngcreator/Main2Activity.kt b/app-test/src/main/java/oupson/apngcreator/ViewerActivity.kt
similarity index 60%
rename from app-test/src/main/java/oupson/apngcreator/Main2Activity.kt
rename to app-test/src/main/java/oupson/apngcreator/ViewerActivity.kt
index d502b43..ca2359f 100644
--- a/app-test/src/main/java/oupson/apngcreator/Main2Activity.kt
+++ b/app-test/src/main/java/oupson/apngcreator/ViewerActivity.kt
@@ -2,32 +2,23 @@ package oupson.apngcreator
import android.Manifest
import android.content.pm.PackageManager
-import android.graphics.Color
import android.os.Bundle
import android.view.View
-import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
-import org.jetbrains.anko.backgroundColor
-import org.jetbrains.anko.imageView
-import org.jetbrains.anko.matchParent
-import org.jetbrains.anko.verticalLayout
+import kotlinx.android.synthetic.main.activity_viewer.*
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
import oupson.apng.CustomAnimationDrawable
import oupson.apng.ExperimentalApngDecoder
-class Main2Activity : AppCompatActivity() {
- private lateinit var imageView : ImageView
+class ViewerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_viewer)
- verticalLayout {
- imageView = imageView().lparams {
- width = matchParent
- height = matchParent
- }
- backgroundColor = Color.parseColor("#323232")
- }
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
@@ -50,26 +41,15 @@ class Main2Activity : AppCompatActivity() {
private fun load() {
val uri = intent.data ?: return
- //val animator = imageView.loadApng(uri, null)
- val drawable = ExperimentalApngDecoder.decodeApng(this, uri)
- imageView.setImageDrawable(drawable)
- if (drawable is CustomAnimationDrawable)
- drawable.start()
- /**
- imageView.onClick {
- try {
- if (animator.isApng) {
- if (animator.isPlaying) {
- animator.pause()
- } else {
- animator.play()
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
+ GlobalScope.launch(Dispatchers.IO) {
+ //val animator = imageView.loadApng(uri, null)
+ val drawable = ExperimentalApngDecoder.decodeApng(this@ViewerActivity, uri)
+ GlobalScope.launch(Dispatchers.Main) {
+ viewerImageView.setImageDrawable(drawable)
+ if (drawable is CustomAnimationDrawable)
+ drawable.start()
}
}
- */
}
override fun onRequestPermissionsResult(requestCode: Int,
diff --git a/app-test/src/main/res/color/drawer_item.xml b/app-test/src/main/res/color/drawer_item.xml
new file mode 100644
index 0000000..9b4dbb0
--- /dev/null
+++ b/app-test/src/main/res/color/drawer_item.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/drawable/ic_create_white_24dp.xml b/app-test/src/main/res/drawable/ic_create_white_24dp.xml
new file mode 100644
index 0000000..46462b5
--- /dev/null
+++ b/app-test/src/main/res/drawable/ic_create_white_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app-test/src/main/res/drawable/ic_java.xml b/app-test/src/main/res/drawable/ic_java.xml
new file mode 100644
index 0000000..8c8d4a2
--- /dev/null
+++ b/app-test/src/main/res/drawable/ic_java.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app-test/src/main/res/drawable/ic_kotlin.xml b/app-test/src/main/res/drawable/ic_kotlin.xml
new file mode 100644
index 0000000..ba43a68
--- /dev/null
+++ b/app-test/src/main/res/drawable/ic_kotlin.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app-test/src/main/res/drawable/ic_menu_white_24dp.xml b/app-test/src/main/res/drawable/ic_menu_white_24dp.xml
new file mode 100644
index 0000000..de103a6
--- /dev/null
+++ b/app-test/src/main/res/drawable/ic_menu_white_24dp.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app-test/src/main/res/layout/activity_java.xml b/app-test/src/main/res/layout/activity_java.xml
deleted file mode 100644
index 0a95e0e..0000000
--- a/app-test/src/main/res/layout/activity_java.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app-test/src/main/res/layout/activity_main.xml b/app-test/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..5e36603
--- /dev/null
+++ b/app-test/src/main/res/layout/activity_main.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/layout/activity_viewer.xml b/app-test/src/main/res/layout/activity_viewer.xml
new file mode 100644
index 0000000..0ec4c0c
--- /dev/null
+++ b/app-test/src/main/res/layout/activity_viewer.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/layout/fragment_java.xml b/app-test/src/main/res/layout/fragment_java.xml
new file mode 100644
index 0000000..f11b925
--- /dev/null
+++ b/app-test/src/main/res/layout/fragment_java.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/layout/fragment_kotlin.xml b/app-test/src/main/res/layout/fragment_kotlin.xml
new file mode 100644
index 0000000..a8462a1
--- /dev/null
+++ b/app-test/src/main/res/layout/fragment_kotlin.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/menu/main_menu.xml b/app-test/src/main/res/menu/main_menu.xml
deleted file mode 100644
index 397dc9c..0000000
--- a/app-test/src/main/res/menu/main_menu.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app-test/src/main/res/menu/navigation_menu.xml b/app-test/src/main/res/menu/navigation_menu.xml
new file mode 100644
index 0000000..f67ef07
--- /dev/null
+++ b/app-test/src/main/res/menu/navigation_menu.xml
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/app-test/src/main/res/values-night/bools.xml b/app-test/src/main/res/values-night/bools.xml
new file mode 100644
index 0000000..1750088
--- /dev/null
+++ b/app-test/src/main/res/values-night/bools.xml
@@ -0,0 +1,4 @@
+
+
+ false
+
\ No newline at end of file
diff --git a/app-test/src/main/res/values-night/colors.xml b/app-test/src/main/res/values-night/colors.xml
new file mode 100644
index 0000000..beb3633
--- /dev/null
+++ b/app-test/src/main/res/values-night/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #fff
+
+ #999999
+
+ #000
+
+ #fff
+
diff --git a/app-test/src/main/res/values/bools.xml b/app-test/src/main/res/values/bools.xml
new file mode 100644
index 0000000..c1210b7
--- /dev/null
+++ b/app-test/src/main/res/values/bools.xml
@@ -0,0 +1,4 @@
+
+
+ true
+
\ No newline at end of file
diff --git a/app-test/src/main/res/values/colors.xml b/app-test/src/main/res/values/colors.xml
index c040895..956c5d3 100644
--- a/app-test/src/main/res/values/colors.xml
+++ b/app-test/src/main/res/values/colors.xml
@@ -1,8 +1,22 @@
- #ffffff
- #ffffff
+ @color/primary
+ @color/primary_dark
#b00020
+ #81c784
+ #b2fab4
+ #519657
+
+ #ff5722
+ #ff8a50
+ #c41c00
+
+ #000
+
#999999
+
+ #ffffff
+
+ #fff
diff --git a/app-test/src/main/res/values/strings.xml b/app-test/src/main/res/values/strings.xml
index 6a10e7a..4391244 100644
--- a/app-test/src/main/res/values/strings.xml
+++ b/app-test/src/main/res/values/strings.xml
@@ -4,4 +4,20 @@
Create APNG
Java Activity
An ImageView with an APNG
+
+ Loaded Image
+
+ Play
+ Pause
+
+ Kotlin Activity
+ Java Activity
+
+ Create
+
+ open
+ close
+
+
+ Hello blank fragment
diff --git a/app-test/src/main/res/values/styles.xml b/app-test/src/main/res/values/styles.xml
index 65e5584..5d8ea12 100644
--- a/app-test/src/main/res/values/styles.xml
+++ b/app-test/src/main/res/values/styles.xml
@@ -1,18 +1,20 @@
-
-