diff --git a/core/src/main/java/com/guet/flexbox/build/FrameFactory.kt b/core/src/main/java/com/guet/flexbox/build/FrameFactory.kt index 88402a18..792365c0 100644 --- a/core/src/main/java/com/guet/flexbox/build/FrameFactory.kt +++ b/core/src/main/java/com/guet/flexbox/build/FrameFactory.kt @@ -44,7 +44,7 @@ internal object FrameFactory : WidgetFactory(), ThreadFactory { return } var width = if (attrs != null) { - dataBinding.tryGetValue(attrs["width"], Int.MIN_VALUE) + dataBinding.tryGetValue(attrs["borderWidth"], Int.MIN_VALUE) } else { Int.MIN_VALUE } diff --git a/core/src/main/java/com/guet/flexbox/build/WidgetFactory.kt b/core/src/main/java/com/guet/flexbox/build/WidgetFactory.kt index 6bcf9da8..93d4c246 100644 --- a/core/src/main/java/com/guet/flexbox/build/WidgetFactory.kt +++ b/core/src/main/java/com/guet/flexbox/build/WidgetFactory.kt @@ -5,7 +5,6 @@ import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.view.View import androidx.annotation.CallSuper -import com.bumptech.glide.request.target.Target import com.facebook.litho.Component import com.facebook.litho.ComponentContext import com.facebook.litho.drawable.ComparableColorDrawable @@ -24,7 +23,7 @@ internal abstract class WidgetFactory> : Transform { internal val mappings = Mappings() init { - numberAttr("width") { _, _, it -> + numberAttr("borderWidth") { _, _, it -> this.widthPx(it.toPx()) } numberAttr("height") { _, _, it -> @@ -163,18 +162,8 @@ internal abstract class WidgetFactory> : Transform { if (backgroundELResult is ComparableGradientDrawable) { backgroundDrawable = backgroundELResult } else if (backgroundELResult is CharSequence && backgroundELResult.isNotEmpty()) { - var width = dataBinding.tryGetValue(attrs["width"], Target.SIZE_ORIGINAL) - if (width <= 0) { - width = Target.SIZE_ORIGINAL - } - var height = dataBinding.tryGetValue(attrs["height"], Target.SIZE_ORIGINAL) - if (height <= 0) { - height = Target.SIZE_ORIGINAL - } backgroundDrawable = NetworkLazyDrawable( c.androidContext, - width.toPx(), - height.toPx(), backgroundELResult ) } diff --git a/core/src/main/java/com/guet/flexbox/widget/BackgroundDrawable.kt b/core/src/main/java/com/guet/flexbox/widget/BackgroundDrawable.kt index b5520c9f..129931b5 100644 --- a/core/src/main/java/com/guet/flexbox/widget/BackgroundDrawable.kt +++ b/core/src/main/java/com/guet/flexbox/widget/BackgroundDrawable.kt @@ -17,19 +17,33 @@ internal class BackgroundDrawable( return true } if (other is BackgroundDrawable) { - var inner = wrappedDrawable - while (inner is DrawableWrapper<*>) { - inner = inner.wrappedDrawable + fun unwrap(drawable: BorderDrawable<*>): Drawable { + var innerDrawable: Drawable = drawable + while (innerDrawable is DrawableWrapper<*>) { + innerDrawable = innerDrawable.wrappedDrawable + } + return innerDrawable } - var otherInner = other.wrappedDrawable - while (otherInner is DrawableWrapper<*>) { - otherInner = otherInner.wrappedDrawable - } - if (inner is ComparableDrawable && otherInner is ComparableDrawable) { - return ComparableDrawable.isEquivalentTo(inner, otherInner) + + val border = wrappedDrawable + val otherBorder = other.wrappedDrawable + if (border.borderWidth == otherBorder.borderWidth + && border.borderColor == otherBorder.borderColor + && border.radius == otherBorder.radius) { + val left = unwrap(border) + val right = unwrap(otherBorder) + return if (left is ComparableDrawable && right is ComparableDrawable) { + ComparableDrawable.isEquivalentTo(left, right) + } else { + left == right + } } } return false } + override fun getWrappedDrawable(): BorderDrawable<*> { + return super.getWrappedDrawable() as BorderDrawable<*> + } + } \ No newline at end of file diff --git a/core/src/main/java/com/guet/flexbox/widget/BorderDrawable.kt b/core/src/main/java/com/guet/flexbox/widget/BorderDrawable.kt index ef681b9b..c598fca5 100644 --- a/core/src/main/java/com/guet/flexbox/widget/BorderDrawable.kt +++ b/core/src/main/java/com/guet/flexbox/widget/BorderDrawable.kt @@ -8,8 +8,8 @@ import android.graphics.drawable.Drawable internal open class BorderDrawable( drawable: T, radius: Int = 0, - var width: Int = 0, - var color: Int = Color.TRANSPARENT + var borderWidth: Int = 0, + var borderColor: Int = Color.TRANSPARENT ) : RoundedDrawable(drawable, radius) { private val paint = Paint().apply { @@ -19,9 +19,9 @@ internal open class BorderDrawable( override fun draw(canvas: Canvas) { super.draw(canvas) - if (width > 0) { - paint.color = color - paint.strokeWidth = width.toFloat() + if (borderWidth > 0) { + paint.color = borderColor + paint.strokeWidth = borderWidth.toFloat() canvas.drawPath(path, paint) } } diff --git a/core/src/main/java/com/guet/flexbox/widget/MatrixDrawable.java b/core/src/main/java/com/guet/flexbox/widget/MatrixDrawable.java index 54b6221a..097d3083 100644 --- a/core/src/main/java/com/guet/flexbox/widget/MatrixDrawable.java +++ b/core/src/main/java/com/guet/flexbox/widget/MatrixDrawable.java @@ -40,6 +40,7 @@ /** * A Drawable that wraps another drawable. + * modify from{@link com.facebook.litho.MatrixDrawable} */ final class MatrixDrawable extends Drawable implements Drawable.Callback, Touchable { diff --git a/core/src/main/java/com/guet/flexbox/widget/NetworkImageSpec.kt b/core/src/main/java/com/guet/flexbox/widget/NetworkImageSpec.kt index d7f6174e..e4230ddf 100644 --- a/core/src/main/java/com/guet/flexbox/widget/NetworkImageSpec.kt +++ b/core/src/main/java/com/guet/flexbox/widget/NetworkImageSpec.kt @@ -39,14 +39,10 @@ internal object NetworkImageSpec { fun onBoundsDefined( c: ComponentContext, layout: ComponentLayout, - layoutWidth: Output, - layoutHeight: Output, - horizontalPadding: Output, - verticalPadding: Output) { - horizontalPadding.set(layout.paddingLeft + layout.paddingRight) - verticalPadding.set(layout.paddingTop + layout.paddingBottom) - layoutWidth.set(layout.width) - layoutHeight.set(layout.height) + width: Output, + height: Output) { + width.set(layout.width - (layout.paddingLeft + layout.paddingRight)) + height.set(layout.height - (layout.paddingTop + layout.paddingBottom)) } @OnMount @@ -59,16 +55,12 @@ internal object NetworkImageSpec { @Prop(optional = true) blurRadius: Float, @Prop(optional = true) blurSampling: Float, @Prop(optional = true) scaleType: ScaleType, - @FromBoundsDefined layoutWidth: Int, - @FromBoundsDefined layoutHeight: Int, - @FromBoundsDefined horizontalPadding: Int, - @FromBoundsDefined verticalPadding: Int) { + @FromBoundsDefined width: Int, + @FromBoundsDefined height: Int) { drawable.mount( url, - layoutWidth, - layoutHeight, - horizontalPadding, - verticalPadding, + width, + height, borderRadius, borderWidth, borderColor, diff --git a/core/src/main/java/com/guet/flexbox/widget/NetworkLazyDrawable.kt b/core/src/main/java/com/guet/flexbox/widget/NetworkLazyDrawable.kt index cacca42f..a207d4b4 100644 --- a/core/src/main/java/com/guet/flexbox/widget/NetworkLazyDrawable.kt +++ b/core/src/main/java/com/guet/flexbox/widget/NetworkLazyDrawable.kt @@ -5,7 +5,7 @@ import android.graphics.Canvas import android.graphics.drawable.Drawable import android.text.TextUtils import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.target.SizeReadyCallback import com.bumptech.glide.request.transition.Transition import com.facebook.litho.drawable.ComparableDrawable import com.facebook.litho.drawable.ComparableDrawableWrapper @@ -13,53 +13,45 @@ import java.util.concurrent.atomic.AtomicBoolean internal class NetworkLazyDrawable( c: Context, - private val width: Int, - private val height: Int, private val url: CharSequence) - : ComparableDrawableWrapper(NoOpDrawable()) { + : ComparableDrawableWrapper(NoOpDrawable()), WrapperTarget { - private val loaded = AtomicBoolean(false) + private val trigger = AtomicBoolean(false) private val context = c.applicationContext override fun draw(canvas: Canvas) { - if (loaded.compareAndSet(false, true)) { - Glide.with(context).load(url) - .into(LazyTarget(width, height)) + if (trigger.compareAndSet(false, true)) { + Glide.with(context).load(url).into(this) } else { super.draw(canvas) } } + override fun getSize(cb: SizeReadyCallback) { + cb.onSizeReady(bounds.width(), bounds.height()) + } + override fun isEquivalentTo(other: ComparableDrawable?): Boolean { if (other == this) { return true } if (other is NetworkLazyDrawable) { - return width == other.width - && height == other.height - && TextUtils.equals(url, other.url) + return TextUtils.equals(url, other.url) } return false } - internal inner class LazyTarget( - width: Int, - height: Int - ) : CustomTarget(width, height) { - override fun onLoadCleared(placeholder: Drawable?) { - if (placeholder != null) { - onResourceReady(placeholder, null) - } else { - onResourceReady(NoOpDrawable(), null) - } - } + override fun onResourceReady(resource: Drawable, transition: Transition?) { + resource.bounds = bounds + wrappedDrawable = WrapperTarget.transition(null, resource) + invalidateSelf() + } - override fun onResourceReady( - resource: Drawable, - transition: Transition?) { - resource.bounds = bounds - wrappedDrawable = NetworkMatrixDrawable.transition(null, resource) - invalidateSelf() + override fun onLoadCleared(placeholder: Drawable?) { + if (placeholder != null) { + onResourceReady(placeholder, null) + } else { + onResourceReady(NoOpDrawable(), null) } } } \ No newline at end of file diff --git a/core/src/main/java/com/guet/flexbox/widget/NetworkMatrixDrawable.kt b/core/src/main/java/com/guet/flexbox/widget/NetworkMatrixDrawable.kt index 5f7865a5..a20cf9e8 100644 --- a/core/src/main/java/com/guet/flexbox/widget/NetworkMatrixDrawable.kt +++ b/core/src/main/java/com/guet/flexbox/widget/NetworkMatrixDrawable.kt @@ -1,81 +1,95 @@ package com.guet.flexbox.widget +import android.annotation.TargetApi import android.content.Context import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable -import android.graphics.drawable.TransitionDrawable +import android.os.Build.VERSION_CODES.LOLLIPOP import android.text.TextUtils import android.view.MotionEvent import android.view.View import android.widget.ImageView.ScaleType import com.bumptech.glide.Glide -import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.target.SizeReadyCallback import com.bumptech.glide.request.transition.Transition import com.facebook.litho.DrawableMatrix import com.facebook.litho.Touchable internal class NetworkMatrixDrawable(c: Context) - : BorderDrawable(MatrixDrawable()), Touchable { + : BorderDrawable(MatrixDrawable()), Touchable, WrapperTarget { + private val c: Context = c.applicationContext - private var layoutWidth: Int = 0 - private var layoutHeight: Int = 0 - private var horizontalPadding: Int = 0 - private var verticalPadding: Int = 0 + private var width: Int = 0 + private var height: Int = 0 + private var scaleType = ScaleType.FIT_CENTER fun mount( url: CharSequence, - layoutWidth: Int, - layoutHeight: Int, - horizontalPadding: Int, - verticalPadding: Int, - radius: Int, width: Int, - color: Int, + height: Int, + radius: Int, + borderWidth: Int, + borderColor: Int, blurRadius: Float, blurSampling: Float, scaleType: ScaleType ) { - this.layoutHeight = layoutHeight - this.layoutWidth = layoutWidth - this.horizontalPadding = horizontalPadding - this.verticalPadding = verticalPadding - this.radius = radius this.width = width - this.color = color + this.height = height + this.radius = radius + this.borderWidth = borderWidth + this.borderColor = borderColor + this.scaleType = scaleType if (TextUtils.isEmpty(url)) { notifyChanged(scaleType, ColorDrawable(Color.TRANSPARENT)) } else { - Glide.with(c).load(url) - .apply { - if (blurRadius > 0) { - transform(BlurTransformation( - c, - blurRadius, - blurSampling - )) - } - }.into(DrawableTarget( - layoutWidth - horizontalPadding, - layoutHeight - verticalPadding, - scaleType + Glide.with(c).load(url).apply { + if (blurRadius > 0) { + transform(BlurTransformation( + c, + blurRadius, + blurSampling )) + } + }.into(this) } } + override fun getSize(cb: SizeReadyCallback) { + cb.onSizeReady(width, height) + } + + override fun onLoadCleared(placeholder: Drawable?) { + if (placeholder != null) { + onResourceReady(placeholder, null) + } else { + wrappedDrawable.unmount() + } + } + + override fun onResourceReady( + resource: Drawable, + transition: Transition? + ) { + notifyChanged(scaleType, resource) + } + fun unmount() { wrappedDrawable.unmount() + Glide.with(c).clear(this) } - override fun onTouchEvent(event: MotionEvent?, host: View?): Boolean { + @TargetApi(LOLLIPOP) + override fun onTouchEvent(event: MotionEvent, host: View): Boolean { return wrappedDrawable.onTouchEvent(event, host) } - override fun shouldHandleTouchEvent(event: MotionEvent?): Boolean { + override fun shouldHandleTouchEvent(event: MotionEvent): Boolean { return wrappedDrawable.shouldHandleTouchEvent(event) } - internal fun notifyChanged( + private fun notifyChanged( scaleType: ScaleType, resource: Drawable ) { @@ -86,55 +100,23 @@ internal class NetworkMatrixDrawable(c: Context) || resource.intrinsicWidth <= 0 || resource.intrinsicHeight <= 0) { matrix = null - drawableWidth = layoutWidth - horizontalPadding - drawableHeight = layoutHeight - verticalPadding + drawableWidth = width + drawableHeight = height } else { matrix = DrawableMatrix.create( resource, scaleType, - layoutWidth - horizontalPadding, - layoutHeight - verticalPadding) + width, + height + ) drawableWidth = resource.intrinsicWidth drawableHeight = resource.intrinsicHeight } wrappedDrawable.mount( - transition(wrappedDrawable.mountedDrawable, resource), + WrapperTarget.transition(wrappedDrawable.mountedDrawable, resource), matrix, drawableWidth, drawableHeight ) } - - internal inner class DrawableTarget( - width: Int, - height: Int, - private val scaleType: ScaleType - ) : CustomTarget(width, height) { - - override fun onLoadCleared(placeholder: Drawable?) { - if (placeholder != null) { - onResourceReady(placeholder, null) - } else { - wrappedDrawable.unmount() - } - } - - override fun onResourceReady( - resource: Drawable, - transition: Transition? - ) { - notifyChanged(scaleType, resource) - } - } - - internal companion object { - internal fun transition(current: Drawable?, next: Drawable): Drawable { - val transitionDrawable = TransitionDrawable(arrayOf( - current ?: ColorDrawable(Color.TRANSPARENT), next - )) - transitionDrawable.isCrossFadeEnabled = true - transitionDrawable.startTransition(200) - return transitionDrawable - } - } } \ No newline at end of file diff --git a/core/src/main/java/com/guet/flexbox/widget/WrapperTarget.kt b/core/src/main/java/com/guet/flexbox/widget/WrapperTarget.kt new file mode 100644 index 00000000..25e22f29 --- /dev/null +++ b/core/src/main/java/com/guet/flexbox/widget/WrapperTarget.kt @@ -0,0 +1,64 @@ +package com.guet.flexbox.widget + +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.TransitionDrawable +import com.bumptech.glide.request.Request +import com.bumptech.glide.request.target.SizeReadyCallback +import com.bumptech.glide.request.target.Target +import java.util.* +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write + +internal interface WrapperTarget : Target { + + override fun onLoadFailed(errorDrawable: Drawable?) { + // Intentionally empty, this can be optionally implemented by subclasses. + } + + override fun onLoadStarted(placeholder: Drawable?) { + // Intentionally empty, this can be optionally implemented by subclasses. + } + + override fun onStart() { + // Intentionally empty, this can be optionally implemented by subclasses. + } + + override fun onStop() { + // Intentionally empty, this can be optionally implemented by subclasses. + } + + override fun onDestroy() { + // Intentionally empty, this can be optionally implemented by subclasses. + } + + override fun removeCallback(cb: SizeReadyCallback) { + // Do nothing, this class does not retain SizeReadyCallbacks. + } + + override fun setRequest(request: Request?) { + lock.write { requests[this] = request } + } + + override fun getRequest(): Request? { + return lock.read { return requests[this] } + } + + companion object { + + internal val lock = ReentrantReadWriteLock() + + internal val requests = WeakHashMap() + + internal fun transition(current: Drawable?, next: Drawable): Drawable { + val transitionDrawable = TransitionDrawable(arrayOf( + current ?: ColorDrawable(Color.TRANSPARENT), next + )) + transitionDrawable.isCrossFadeEnabled = true + transitionDrawable.startTransition(200) + return transitionDrawable + } + } +} diff --git a/el/src/main/java/com/guet/flexbox/el/JSONObjectELResolver.kt b/el/src/main/java/com/guet/flexbox/el/JSONObjectELResolver.kt index 5f12d594..d946fa56 100644 --- a/el/src/main/java/com/guet/flexbox/el/JSONObjectELResolver.kt +++ b/el/src/main/java/com/guet/flexbox/el/JSONObjectELResolver.kt @@ -38,7 +38,7 @@ internal object JSONObjectELResolver : ELResolver() { val feats = ArrayList(base.length()) base.keys().forEach { key -> val desc = FeatureDescriptor() - desc.displayName = key.toString() + desc.displayName = key desc.shortDescription = "" desc.isExpert = false desc.isHidden = false