Created
June 2, 2014 13:49
-
-
Save melanke/b92ab0ff7a78bfdf712d to your computer and use it in GitHub Desktop.
MLCoverflow Xamarin Implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using Android.App; | |
using Android.Content; | |
using Android.OS; | |
using Android.Runtime; | |
using Android.Views; | |
using Android.Widget; | |
using Android.Graphics; | |
using Android.Util; | |
using Android.Views.Animations; | |
using Android.Content.Res; | |
namespace br.com.martinlabs.commons.android | |
{ | |
public class MLCoverFlow : Gallery | |
{ | |
/** | |
* Graphics Camera used for transforming the matrix of ImageViews. | |
*/ | |
private Camera mCamera = new Camera(); | |
/** | |
* The maximum angle the Child ImageView will be rotated by. | |
*/ | |
private int mMaxRotationAngle = 60; | |
/** | |
* The maximum zoom on the centre Child. | |
*/ | |
private int mMaxZoom = -300; | |
/** | |
* The Centre of the Coverflow. | |
*/ | |
private int mCoveflowCenter; | |
/** The image height. */ | |
private float imageHeight; | |
/** The image width. */ | |
private float imageWidth; | |
/** The reflection gap. */ | |
private float reflectionGap; | |
/** The with reflection. */ | |
private bool withReflection; | |
/** The image reflection ratio. */ | |
private float imageReflectionRatio; | |
/** | |
* Gets the image height. | |
* | |
* @return the image height | |
*/ | |
public float GetImageHeight() { | |
return imageHeight; | |
} | |
/** | |
* Sets the image height. | |
* | |
* @param imageHeight | |
* the new image height | |
*/ | |
public void SetImageHeight(float imageHeight) { | |
this.imageHeight = imageHeight; | |
} | |
/** | |
* Gets the image width. | |
* | |
* @return the image width | |
*/ | |
public float GetImageWidth() { | |
return imageWidth; | |
} | |
/** | |
* Sets the image width. | |
* | |
* @param imageWidth | |
* the new image width | |
*/ | |
public void SetImageWidth(float imageWidth) { | |
this.imageWidth = imageWidth; | |
} | |
/** | |
* Gets the reflection gap. | |
* | |
* @return the reflection gap | |
*/ | |
public float GetReflectionGap() { | |
return reflectionGap; | |
} | |
/** | |
* Sets the reflection gap. | |
* | |
* @param reflectionGap | |
* the new reflection gap | |
*/ | |
public void SetReflectionGap(float reflectionGap) { | |
this.reflectionGap = reflectionGap; | |
} | |
/** | |
* Checks if is with reflection. | |
* | |
* @return true, if is with reflection | |
*/ | |
public bool IsWithReflection() { | |
return withReflection; | |
} | |
/** | |
* Sets the with reflection. | |
* | |
* @param withReflection | |
* the new with reflection | |
*/ | |
public void SetWithReflection(bool withReflection) { | |
this.withReflection = withReflection; | |
} | |
/** | |
* Sets the image reflection ratio. | |
* | |
* @param imageReflectionRatio | |
* the new image reflection ratio | |
*/ | |
public void SetImageReflectionRatio(float imageReflectionRatio) { | |
this.imageReflectionRatio = imageReflectionRatio; | |
} | |
/** | |
* Gets the image reflection ratio. | |
* | |
* @return the image reflection ratio | |
*/ | |
public float GetImageReflectionRatio() { | |
return imageReflectionRatio; | |
} | |
public MLCoverFlow(Context context) : | |
base(context) { | |
this.SetStaticTransformationsEnabled(true); | |
} | |
public MLCoverFlow(Context context, IAttributeSet attrs) : | |
this(context, attrs, Android.Resource.Attribute.GalleryStyle){ | |
} | |
public MLCoverFlow(Context context, IAttributeSet attrs, int defStyle) : | |
base(context, attrs, defStyle) { | |
ParseAttributes(context, attrs); | |
this.SetStaticTransformationsEnabled(true); | |
} | |
/** | |
* Get the max rotational angle of the image. | |
* | |
* @return the mMaxRotationAngle | |
*/ | |
public int getMaxRotationAngle() { | |
return mMaxRotationAngle; | |
} | |
/** | |
* Sets the. | |
* | |
* @param adapter | |
* the new adapter | |
*/ | |
public void SetAdapter(ISpinnerAdapter value) | |
{ | |
if (!(value is MLAbstractCoverFlowImageAdapter)) | |
{ | |
return; | |
} | |
MLAbstractCoverFlowImageAdapter coverAdapter = (MLAbstractCoverFlowImageAdapter)value; | |
coverAdapter.SetWidth(imageWidth); | |
coverAdapter.SetHeight(imageHeight); | |
if (withReflection) | |
{ | |
MLReflectingImageAdapter reflectAdapter = new MLReflectingImageAdapter(coverAdapter); | |
reflectAdapter.SetReflectionGap(reflectionGap); | |
reflectAdapter.SetWidthRatio(imageReflectionRatio); | |
reflectAdapter.SetWidth(imageWidth); | |
reflectAdapter.SetHeight(imageHeight * (1 + imageReflectionRatio)); | |
base.Adapter = reflectAdapter; | |
} | |
else | |
{ | |
base.Adapter = value; | |
} | |
} | |
/** | |
* Set the max rotational angle of each image. | |
* | |
* @param maxRotationAngle | |
* the mMaxRotationAngle to set | |
*/ | |
public void SetMaxRotationAngle(int maxRotationAngle) { | |
mMaxRotationAngle = maxRotationAngle; | |
} | |
/** | |
* Get the Max zoom of the centre image. | |
* | |
* @return the mMaxZoom | |
*/ | |
public int GetMaxZoom() { | |
return mMaxZoom; | |
} | |
/** | |
* Set the max zoom of the centre image. | |
* | |
* @param maxZoom | |
* the mMaxZoom to set | |
*/ | |
public void SetMaxZoom(int maxZoom) { | |
mMaxZoom = maxZoom; | |
} | |
/** | |
* Get the Centre of the Coverflow. | |
* | |
* @return The centre of this Coverflow. | |
*/ | |
private int GetCenterOfCoverflow() { | |
return (Width - PaddingLeft - PaddingRight) / 2 + PaddingLeft; | |
} | |
/** | |
* Get the Centre of the View. | |
* | |
* @return The centre of the given view. | |
*/ | |
private static int GetCenterOfView(View view) { | |
return view.Left + view.Width / 2; | |
} | |
protected override bool GetChildStaticTransformation(View child, Transformation t) | |
{ | |
Console.WriteLine("child left: " + child.Left); | |
int childCenter = GetCenterOfView(child); | |
int childWidth = child.Width; | |
int rotationAngle = 0; | |
t.Clear(); | |
t.TransformationType = TransformationTypes.Matrix; | |
if (childCenter == mCoveflowCenter) { | |
TransformImageBitmap((ImageView) child, t, 0); | |
} else { | |
rotationAngle = (int) ((float) (mCoveflowCenter - childCenter) / childWidth * mMaxRotationAngle); | |
if (Math.Abs(rotationAngle) > mMaxRotationAngle) { | |
rotationAngle = rotationAngle < 0 ? -mMaxRotationAngle : mMaxRotationAngle; | |
} | |
TransformImageBitmap((ImageView) child, t, rotationAngle); | |
} | |
return true; | |
} | |
/** | |
* This is called during layout when the size of this view has changed. If | |
* you were just added to the view hierarchy, you're called with the old | |
* values of 0. | |
* | |
* @param w | |
* Current width of this view. | |
* @param h | |
* Current height of this view. | |
* @param oldw | |
* Old width of this view. | |
* @param oldh | |
* Old height of this view. | |
*/ | |
protected override void OnSizeChanged(int w, int h, int oldw, int oldh) { | |
mCoveflowCenter = GetCenterOfCoverflow(); | |
base.OnSizeChanged(w, h, oldw, oldh); | |
} | |
/** | |
* Transform the Image Bitmap by the Angle passed. | |
* | |
* @param imageView | |
* ImageView the ImageView whose bitmap we want to rotate | |
* @param t | |
* transformation | |
* @param rotationAngle | |
* the Angle by which to rotate the Bitmap | |
*/ | |
private void TransformImageBitmap(ImageView child, Transformation t, int rotationAngle) { | |
mCamera.Save(); | |
Matrix imageMatrix = t.Matrix; | |
int height = child.LayoutParameters.Height; | |
int width = child.LayoutParameters.Width; | |
int rotation = Math.Abs(rotationAngle); | |
mCamera.Translate(0.0f, 0.0f, 100.0f); | |
// As the angle of the view gets less, zoom in | |
if (rotation < mMaxRotationAngle) { | |
float zoomAmount = (float) (mMaxZoom + rotation * 1.5); | |
mCamera.Translate(0.0f, 0.0f, zoomAmount); | |
} | |
mCamera.RotateY(rotationAngle); | |
mCamera.GetMatrix(imageMatrix); | |
imageMatrix.PreTranslate(-(width / 2.0f), -(height / 2.0f)); | |
imageMatrix.PostTranslate((width / 2.0f), (height / 2.0f)); | |
mCamera.Restore(); | |
} | |
/** | |
* Parses the attributes. | |
* | |
* @param context | |
* the context | |
* @param attrs | |
* the attrs | |
*/ | |
private void ParseAttributes(Context context, IAttributeSet attrs) { | |
TypedArray a = context.ObtainStyledAttributes(attrs, Resource.Styleable.CoverFlow); | |
try { | |
imageWidth = a.GetDimension(Resource.Styleable.CoverFlow_imageWidth, 480); | |
imageHeight = a.GetDimension(Resource.Styleable.CoverFlow_imageHeight, 320); | |
withReflection = a.GetBoolean(Resource.Styleable.CoverFlow_withReflection, false); | |
imageReflectionRatio = a.GetFloat(Resource.Styleable.CoverFlow_imageReflectionRatio, 0.2f); | |
reflectionGap = a.GetDimension(Resource.Styleable.CoverFlow_reflectionGap, 4); | |
SetSpacing(-15); | |
} finally { | |
a.Recycle(); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment