Skip to content

Instantly share code, notes, and snippets.

@melanke
Created June 2, 2014 13:49
Show Gist options
  • Save melanke/b92ab0ff7a78bfdf712d to your computer and use it in GitHub Desktop.
Save melanke/b92ab0ff7a78bfdf712d to your computer and use it in GitHub Desktop.
MLCoverflow Xamarin Implementation
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