分类:C#、Android、VS2015;
创建日期:2016-03-21
该例子演示如何动画缩放图片,实现类似“点击看大图”的效果。
1、运行截图
2、设计步骤
(1)添加图片
在Resources/no-dpi文件夹下添加4张图片(2个缩略图,2个大图)。
(2)添加ch2104MyImageButton.cs
using Android.Content; using Android.Widget; using System.Drawing; using Android.Graphics.Drawables; using Android.Util; using Android.Content.Res; using Android.Graphics; using Color = Android.Graphics.Color; namespace MyDemos.SrcDemos { /// <summary> /// 演示drawable-nodpi文件夹下的图片资源缩放(点击看大图) /// </summary> public class ch2104MyImageButton : ImageButton { private Rectangle cachedBounds; private Drawable foregroundDrawable; public ch2104MyImageButton(Context context) : this(context, null) { } public ch2104MyImageButton(Context context, IAttributeSet attrs) : this(context, attrs, 0) { } public ch2104MyImageButton(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle) { Init(); } protected override void DrawableStateChanged() { base.DrawableStateChanged(); if (foregroundDrawable.IsStateful) { foregroundDrawable.SetState(GetDrawableState()); } Invalidate(); } protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); base.OnDraw(canvas); foregroundDrawable.SetBounds(cachedBounds.Left, cachedBounds.Top, cachedBounds.Right, cachedBounds.Bottom); foregroundDrawable.Draw(canvas); } protected override void OnSizeChanged(int w, int h, int oldw, int oldh) { base.OnSizeChanged(w, h, oldw, oldh); cachedBounds = new Rectangle(0, 0, w, h); } private void Init() { SetBackgroundColor(Color.White); SetPadding(0, 0, 0, 0); TypedArray a = Context.ObtainStyledAttributes(new[] { Android.Resource.Attribute.SelectableItemBackground }); foregroundDrawable = a.GetDrawable(0); foregroundDrawable.SetCallback(this); a.Recycle(); } } }
(3)添加ch2104Zoom.axml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="16dp"> <TextView style="?android:textAppearanceSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="提示:单击缩略图【放大/缩小】该图片。" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:orientation="horizontal"> <MyDemos.SrcDemos.ch2104MyImageButton android:id="@+id/thumb_button_1" android:layout_width="100dp" android:layout_height="75dp" android:layout_marginRight="1dp" android:src="@drawable/ch2103thumb1" android:scaleType="centerCrop" android:contentDescription="缩略图1" /> <MyDemos.SrcDemos.ch2104MyImageButton android:id="@+id/thumb_button_2" android:layout_width="100dp" android:layout_height="75dp" android:src="@drawable/ch2103thumb2" android:scaleType="centerCrop" android:contentDescription="缩略图2" /> </LinearLayout> </LinearLayout> <ImageView android:id="@+id/expanded_image" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="invisible" android:contentDescription="这是放大后的图片(点击消失)" /> </FrameLayout>
(4)添加ch2104ZoomActivity.cs
using System; using System.Collections.Generic; using Android.App; using Android.OS; using Android.Views; using Android.Widget; using Android.Animation; using Android.Graphics; using Android.Views.Animations; namespace MyDemos.SrcDemos { [Activity(Label = "【例21-4】图片动画缩放示例")] public class ch2104ZoomActivity : Activity { private Animator currentAnimator; private int shortAnimationDuration; private Dictionary<int, AnimatorSet> expandingAnimators; private Dictionary<int, AnimatorSet> shrinkingAnimators; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.ch2104Zoom); shortAnimationDuration = Resources.GetInteger(Android.Resource.Integer.ConfigShortAnimTime); expandingAnimators = new Dictionary<int, AnimatorSet>(2); shrinkingAnimators = new Dictionary<int, AnimatorSet>(2); View thumb1View = FindViewById(Resource.Id.thumb_button_1); thumb1View.Tag = Resource.Drawable.ch2103image1; thumb1View.Click += ZoomImageFromThumb; View thumb2View = FindViewById(Resource.Id.thumb_button_2); thumb2View.Tag = Resource.Drawable.ch2103image2; thumb2View.Click += ZoomImageFromThumb; } /// <summary> /// 控制ImageView的放大速率 /// </summary> /// <param name="startBounds">缩略图的矩形区域</param> /// <param name="finalBounds">大图的可见区域</param> /// <returns></returns> private static float CalculateStartScale(Rect startBounds, Rect finalBounds) { float startScale; float finalBoundsRatio = finalBounds.Width() / (float)finalBounds.Height(); float startBoundsRatio = startBounds.Width() / (float)startBounds.Height(); if (finalBoundsRatio > startBoundsRatio) { // 横向展开 startScale = (float)startBounds.Height() / finalBounds.Height(); float startWidth = startScale * finalBounds.Width(); float deltaWidth = (startWidth - startBounds.Width()) / 2; startBounds.Left -= (int)deltaWidth; startBounds.Right += (int)deltaWidth; } else { // 纵向展开 startScale = (float)startBounds.Width() / finalBounds.Width(); float startHeight = startScale * finalBounds.Height(); float deltaHeight = (startHeight - startBounds.Height()) / 2; startBounds.Top -= (int)deltaHeight; startBounds.Bottom += (int)deltaHeight; } return startScale; } /// <summary> /// 创建展开的动画集合 - 让缩略图看起来逐渐变大 /// </summary> /// <param name="expandedView">缩略图放大用的ImageView</param> /// <param name="startBounds">缩略图的可见区域(全局坐标)</param> /// <param name="finalBounds">放大后的矩形区域(全局坐标)</param> /// <param name="startScale"></param> /// <returns></returns> private AnimatorSet BuildExpandingAnimatorSet(ImageView expandedView, Rect startBounds, Rect finalBounds, float startScale) { // 按顺序缓存每次展开的动画集合,这些实例都是从初始位置开始 int key = startBounds.GetHashCode(); if (expandingAnimators.ContainsKey(key)) { return expandingAnimators[key]; } AnimatorSet expandSet = new AnimatorSet(); expandSet.Play(ObjectAnimator.OfFloat(expandedView, View.X, startBounds.Left, finalBounds.Left)) .With(ObjectAnimator.OfFloat(expandedView, View.Y, startBounds.Top, finalBounds.Top)) .With(ObjectAnimator.OfFloat(expandedView, "ScaleX", startScale, 1f)) .With(ObjectAnimator.OfFloat(expandedView, "ScaleY", startScale, 1f)); expandSet.SetDuration(shortAnimationDuration); expandSet.SetInterpolator(new DecelerateInterpolator()); expandSet.AnimationEnd += NullOutCurrentAnimator; expandSet.AnimationCancel += NullOutCurrentAnimator; expandingAnimators.Add(key, expandSet); return expandSet; } private void NullOutCurrentAnimator(object sender, EventArgs eventArgs) { if (currentAnimator == null) { return; } currentAnimator = null; } /// <summary> /// 创建从大图逐步缩小到缩略图的动画集合 /// </summary> /// <param name="bigView">大图的视图</param> /// <param name="thumbView">缩略图的视图</param> /// <param name="startBounds">缩略图变为可见的区域</param> /// <param name="scale">缩放速率</param> /// <returns></returns> private AnimatorSet BuildShrinkingAnimatorSet(View bigView, View thumbView, Rect startBounds, float scale) { if (shrinkingAnimators.ContainsKey(thumbView.Id)) { return shrinkingAnimators[thumbView.Id]; } AnimatorSet shrinkSet = new AnimatorSet(); shrinkSet.Play(ObjectAnimator.OfFloat(bigView, View.X, startBounds.Left)) .With(ObjectAnimator.OfFloat(bigView, View.Y, startBounds.Top)) .With(ObjectAnimator.OfFloat(bigView, "ScaleX", scale)) .With(ObjectAnimator.OfFloat(bigView, "ScaleY", scale)); shrinkSet.SetDuration(shortAnimationDuration); shrinkSet.SetInterpolator(new DecelerateInterpolator()); shrinkSet.AnimationEnd += (sender1, args1) => { thumbView.Alpha = 1.0f; bigView.Visibility = ViewStates.Gone; NullOutCurrentAnimator(sender1, args1); }; shrinkSet.AnimationCancel += (sender1, args1) => { thumbView.Alpha = 1.0f; bigView.Visibility = ViewStates.Gone; NullOutCurrentAnimator(sender1, args1); }; shrinkingAnimators.Add(thumbView.Id, shrinkSet); return shrinkSet; } /// <summary> /// 获取控制展开图片的ImageView的引用 /// </summary> /// <param name="thumbView"></param> /// <returns></returns> private ImageView GetExpandedImageView(View thumbView) { ImageView expandedImageView = FindViewById<ImageView>(Resource.Id.expanded_image); int finalImageResourceId = (int)thumbView.Tag; // In this example we store the resource id of the big image in the tag of the thumbnail. expandedImageView.SetImageResource(finalImageResourceId); thumbView.Alpha = 0.2f; //0f; expandedImageView.Visibility = ViewStates.Visible; expandedImageView.PivotX = 0f; expandedImageView.PivotY = 0f; return expandedImageView; } private void ZoomImageFromThumb(object sender, EventArgs eventArgs) { View thumbView = (View)sender; ImageView expandedImageView = GetExpandedImageView(thumbView); if (currentAnimator != null) { currentAnimator.Cancel(); } Rect startBounds = new Rect(); Rect finalBounds = new Rect(); Point globalOffset = new Point(); thumbView.GetGlobalVisibleRect(startBounds); FindViewById(Resource.Id.container).GetGlobalVisibleRect(finalBounds, globalOffset); startBounds.Offset(-globalOffset.X, -globalOffset.Y); finalBounds.Offset(-globalOffset.X, -globalOffset.Y); float startScale = CalculateStartScale(startBounds, finalBounds); AnimatorSet expandSet = BuildExpandingAnimatorSet(expandedImageView, startBounds, finalBounds, startScale); expandSet.Start(); currentAnimator = expandSet; expandedImageView.Click += (o, args) => { if (currentAnimator != null) { currentAnimator.Cancel(); } AnimatorSet shrinkSet = BuildShrinkingAnimatorSet(expandedImageView, thumbView, startBounds, startScale); shrinkSet.Start(); currentAnimator = shrinkSet; }; } } }