Skip to content

Commit

Permalink
Android: Fixed #353 - incorrect aspect ratio when using fade animation
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-luberda committed Nov 7, 2016
1 parent c048b7b commit 257fbbd
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 128 deletions.
65 changes: 25 additions & 40 deletions source/FFImageLoading.Droid/Drawables/FFBitmapDrawable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class FFBitmapDrawable : SelfDisposingBitmapDrawable
bool animating;
int alpha = 255;
float fadeDuration = 200;
float normalized = 1f;
bool placeholderInitialized;
Rect orgRect;

public FFBitmapDrawable(Resources res, Bitmap bitmap) : base(res, bitmap)
{
Expand Down Expand Up @@ -58,11 +59,10 @@ public void SetPlaceholder(BitmapDrawable drawable, int animationDuration)
{
if (!animating)
{
normalized = 0f;
alpha = 255;
fadeDuration = animationDuration;
startTimeMillis = SystemClock.UptimeMillis();
placeholder = drawable;
placeholder = drawable.GetConstantState().NewDrawable().Mutate() as BitmapDrawable;
animating = true;
}
}
Expand All @@ -77,18 +77,24 @@ public int FadeDuration
get { return (int)fadeDuration; }
}

protected override void OnBoundsChange(Rect bounds)
{
orgRect = bounds;
placeholderInitialized = false;
base.OnBoundsChange(bounds);
}

public override void Draw(Canvas canvas)
{
try
{
if (!animating)
{
normalized = 1f;
base.Draw(canvas);
}
else
{
normalized = (SystemClock.UptimeMillis() - startTimeMillis) / fadeDuration;
var normalized = (SystemClock.UptimeMillis() - startTimeMillis) / fadeDuration;
if (normalized >= 1f)
{
animating = false;
Expand All @@ -100,6 +106,20 @@ public override void Draw(Canvas canvas)
{
if (IsBitmapDrawableValid(placeholder))
{
if (!placeholderInitialized)
{
var placeholderSizeRatio = canvas.Width > canvas.Height ?
(double)orgRect.Right / placeholder.IntrinsicWidth
: (double)orgRect.Bottom / placeholder.IntrinsicHeight;

var scaledWidth = placeholderSizeRatio * placeholder.IntrinsicWidth;
var newOffset = (double)orgRect.CenterX() - scaledWidth / 2;
placeholder.Gravity = Android.Views.GravityFlags.Fill;
placeholder.SetBounds((int)newOffset, orgRect.Top, orgRect.Right, orgRect.Bottom);

placeholderInitialized = true;
}

placeholder.Draw(canvas);
}

Expand All @@ -119,41 +139,6 @@ bool IsBitmapDrawableValid(BitmapDrawable bitmapDrawable)
&& bitmapDrawable.Handle != IntPtr.Zero && !bitmapDrawable.Bitmap.IsRecycled;
}

public override int IntrinsicHeight
{
get
{
try
{
if (animating && normalized < 0.8f && IsBitmapDrawableValid(placeholder))
{
return placeholder.IntrinsicHeight;
}
}
catch (Exception) { }

return base.IntrinsicHeight;
}
}

public override int IntrinsicWidth
{
get
{
try
{
if (animating && normalized < 0.8f && IsBitmapDrawableValid(placeholder))
{
return placeholder.IntrinsicWidth;
}
}
catch (Exception) {}

return base.IntrinsicWidth;
}
}


public override void SetAlpha(int alpha)
{
try
Expand Down
183 changes: 101 additions & 82 deletions source/FFImageLoading.Droid/Drawables/SelfDisposingBitmapDrawable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,13 @@ namespace FFImageLoading.Drawables
/// </summary>
public class SelfDisposingBitmapDrawable : BitmapDrawable, ISelfDisposingBitmapDrawable
{
private const string TAG = "SelfDisposingBitmapDrawable";

const string TAG = "SelfDisposingBitmapDrawable";
protected readonly object monitor = new object();

private int cache_ref_count;
private int display_ref_count;
private int retain_ref_count;

private bool is_bitmap_disposed;

public string InCacheKey { get; set; }

/// <summary>
/// Occurs when internal displayed reference count has reached 0.
/// It is raised before the counts are rechecked, and thus before
/// any resources have potentially been freed.
/// </summary>
public event EventHandler NoLongerDisplayed;

/// <summary>
/// Occurs when internal displayed reference count goes from 0 to 1.
/// Once the internal reference count is > 1 this event will not be raised
/// on subsequent calls to SetIsDisplayed(bool).
/// </summary>
public event EventHandler Displayed;

public long SizeInBytes {
get {
if (HasValidBitmap) {
return Bitmap.Height * Bitmap.RowBytes;
}
return 0;
}
}
int cache_ref_count;
int display_ref_count;
int retain_ref_count;
bool is_bitmap_disposed;

public SelfDisposingBitmapDrawable() : base()
{
Expand Down Expand Up @@ -95,8 +68,36 @@ public SelfDisposingBitmapDrawable(Resources resources, Bitmap bitmap) : base(re
{
}

public SelfDisposingBitmapDrawable(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
{
public SelfDisposingBitmapDrawable(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)
{
}

public string InCacheKey { get; set; }

/// <summary>
/// Occurs when internal displayed reference count has reached 0.
/// It is raised before the counts are rechecked, and thus before
/// any resources have potentially been freed.
/// </summary>
public event EventHandler NoLongerDisplayed;

/// <summary>
/// Occurs when internal displayed reference count goes from 0 to 1.
/// Once the internal reference count is > 1 this event will not be raised
/// on subsequent calls to SetIsDisplayed(bool).
/// </summary>
public event EventHandler Displayed;

public long SizeInBytes
{
get
{
if (HasValidBitmap)
{
return Bitmap.Height * Bitmap.RowBytes;
}
return 0;
}
}

public void SetNoLongerDisplayed()
Expand All @@ -110,7 +111,6 @@ public void SetNoLongerDisplayed()

/// <summary>
/// This should only be called by Views that are actually going to draw the drawable.
///
/// Increments or decrements the internal displayed reference count.
/// If the internal reference count becomes 0, NoLongerDisplayed will be raised.
/// If the internal reference count becomes 1, Displayed will be raised.
Expand All @@ -121,32 +121,33 @@ public void SetNoLongerDisplayed()
public void SetIsDisplayed(bool isDisplayed)
{
EventHandler handler = null;
lock (monitor)
{
if (isDisplayed && !HasValidBitmap)
{
System.Diagnostics.Debug.WriteLine("Cannot redisplay this drawable, its resources have been disposed.");
}
else if (isDisplayed)
{
display_ref_count++;
if (display_ref_count == 1) {
handler = Displayed;
}
}
else
{
display_ref_count--;
}

if (display_ref_count <= 0)
lock (monitor)
{
if (isDisplayed && !HasValidBitmap)
{
display_ref_count = 0;
handler = NoLongerDisplayed;
}
System.Diagnostics.Debug.WriteLine("Cannot redisplay this drawable, its resources have been disposed.");
}
else if (isDisplayed)
{
display_ref_count++;
if (display_ref_count == 1)
{
handler = Displayed;
}
}
else
{
display_ref_count--;
}

if (display_ref_count <= 0)
{
display_ref_count = 0;
handler = NoLongerDisplayed;
}
}
if (handler != null)
{
if (handler != null)
{
handler(this, EventArgs.Empty);
}
CheckState();
Expand All @@ -162,10 +163,13 @@ public void SetIsDisplayed(bool isDisplayed)
/// <param name="isCached">If set to <c>true</c> is cached.</param>
public void SetIsCached(bool isCached)
{
lock (monitor) {
if (isCached) {
lock (monitor)
{
if (isCached)
{
cache_ref_count++;
} else {
}
else {
cache_ref_count--;
}
}
Expand All @@ -184,46 +188,58 @@ public void SetIsCached(bool isCached)
/// <param name="isRetained">If set to <c>true</c> is retained.</param>
public void SetIsRetained(bool isRetained)
{
lock (monitor) {
if (isRetained) {
lock (monitor)
{
if (isRetained)
{
retain_ref_count++;
} else {
}
else {
retain_ref_count--;
}
}
CheckState();
}

public bool IsRetained {
get {
lock (monitor) {
public bool IsRetained
{
get
{
lock (monitor)
{
return retain_ref_count > 0;
}
}
}

protected virtual void OnFreeResources()
{
lock (monitor) {
if (Bitmap != null && Bitmap.Handle != IntPtr.Zero)
Bitmap.Dispose();

lock (monitor)
{
if (Bitmap != null && Bitmap.Handle != IntPtr.Zero)
Bitmap.Dispose();

is_bitmap_disposed = true;
}
}

private void CheckState()
void CheckState()
{
lock (monitor) {
if (ShouldFreeResources) {
lock (monitor)
{
if (ShouldFreeResources)
{
OnFreeResources();
}
}
}

private bool ShouldFreeResources {
get {
lock (monitor) {
bool ShouldFreeResources
{
get
{
lock (monitor)
{
return cache_ref_count <= 0 &&
display_ref_count <= 0 &&
retain_ref_count <= 0 &&
Expand All @@ -232,10 +248,13 @@ private bool ShouldFreeResources {
}
}

public virtual bool HasValidBitmap {
get {
lock (monitor) {
return Bitmap != null && Bitmap.Handle != IntPtr.Zero && !is_bitmap_disposed && !Bitmap.IsRecycled;
public virtual bool HasValidBitmap
{
get
{
lock (monitor)
{
return Bitmap != null && Bitmap.Handle != IntPtr.Zero && !is_bitmap_disposed && !Bitmap.IsRecycled;
}
}
}
Expand Down
Loading

0 comments on commit 257fbbd

Please sign in to comment.