menu selection for rotary effects

Source: Internet
Author: User

1. java files:

Package us.eiyou.financial_management_service;

Import java.util.ArrayList;
Import java.util.Collections;
Import Java.util.Comparator;

Import Android.animation.Animator;
Import Android.animation.AnimatorListenerAdapter;
Import Android.animation.AnimatorSet;
Import Android.animation.ObjectAnimator;
Import Android.animation.ValueAnimator;
Import Android.animation.ValueAnimator.AnimatorUpdateListener;
Import Android.content.Context;
Import Android.util.AttributeSet;
Import android.view.MotionEvent;
Import Android.view.VelocityTracker;
Import Android.view.View;
Import Android.view.ViewTreeObserver;
Import Android.view.animation.DecelerateInterpolator;
Import Android.widget.FrameLayout;

Rotatecard (custom rotation view)
The item is clicked with a magnified animation effect
Quick swipe and finger release will spin
public class Rotatecard extends Framelayout {

Private arraylist<rotatecardviewholder> viewholderlist;
Private arraylist<view> viewlist;
private int Ovala, ovalb;//long half axis of elliptical trajectory, short half axis
private int parentwidth, parentheight;//Rotatecard's wide height
private int Viewwidth, width of view in viewheight;//Viewset
Layoutparams viewpparams;//View's Layoutparams
Private float angleoffset;//The degree of rotation around the center of the ellipse for each sliding pixel of a finger

Private Rotatecardontouchlistener mtouchlistener;//for Rotatecard and child view, handles sliding events

Increase monitoring before drawing to obtain rotatecard width and height
Private Viewtreeobserver.onpredrawlistener Onpredrawlistener = new Viewtreeobserver.onpredrawlistener () {
@Override
public Boolean Onpredraw () {
Parentwidth = RotateCard.this.getMeasuredWidth ();
Parentheight = RotateCard.this.getMeasuredHeight ();
Angleoffset = (float) ((180.0/parentwidth) * 1.5);

LOG.I (Info_tag, "parentwidth:" + parentwidth);
LOG.I (Info_tag, "parentheight:" + parentheight);
LOG.I (Info_tag, "Angleoffset:" + angleoffset);

if (viewlist! = null && viewlist.size () > 0) {
Aftergetparamsandviews ();
}

Remove monitoring
RotateCard.this.getViewTreeObserver (). Removeonpredrawlistener (
Onpredrawlistener);
return true;
}
};

Public Rotatecard (Context context) {
Super (context);
TODO auto-generated Constructor stub
Init ();
}

Public Rotatecard (context context, AttributeSet Attrs) {
Super (context, attrs);
TODO auto-generated Constructor stub
Init ();
}

Public Rotatecard (context context, AttributeSet attrs, int defstyle) {
Super (context, attrs, Defstyle);
TODO auto-generated Constructor stub
Init ();
}

private void init () {
Increase the listening before the Rotatecard is drawn
RotateCard.this.getViewTreeObserver (). Addonpredrawlistener (
Onpredrawlistener);

Increased rotatecard of sliding monitoring
Mtouchlistener = new Rotatecardontouchlistener ();
This.setontouchlistener (Mtouchlistener);
}

/**
* You must ensure that each view of the incoming view collection is the same size, otherwise the display may not be accurate
*
* @param viewset
* View Collection
*/
public void Commitviews (arraylist<view> viewlist, int viewwidth,
int viewheight) {
This.removeallviews ();
This.viewlist = viewlist;
This.viewwidth = Viewwidth;
This.viewheight = Viewheight;
Viewpparams = new Layoutparams (viewwidth, viewheight);
LOG.I (Info_tag, "viewwidth:" + viewwidth);
LOG.I (Info_tag, "viewheight:" + viewheight);

if (parentwidth! = 0 && Parentheight! = 0) {
Aftergetparamsandviews ();
}
}

/**
* You must ensure that each view of the incoming view collection is the same size, otherwise the display may not be accurate
* There should be no one whose view is not a circle or a square? The input diameter or the length of the side is fine.
*
* @param viewset
* View Collection
*/
public void Commitviews (arraylist<view> viewlist, int viewwidthheight) {
This.removeallviews ();
This.viewlist = viewlist;
This.viewwidth = Viewwidthheight;
This.viewheight = Viewwidthheight;
Viewpparams = new Layoutparams (viewwidth, viewheight);
LOG.I (Info_tag, "viewwidth:" + viewwidth);
LOG.I (Info_tag, "viewheight:" + viewheight);

if (parentwidth! = 0 && Parentheight! = 0) {
Aftergetparamsandviews ();
}
}

/**
* This function is called after Rotatecard has been obtained and the Commitviews function has been called
*/
private void Aftergetparamsandviews () {

Ovala = (parentwidth-viewwidth)/2;
OVALB = (int) ((Parentheight-viewheight * 1.5)/2);

int viewnum = Viewlist.size ();
float Angleperview = (float) (360.0/viewnum);

LOG.I (Info_tag, "Ovala:" + Ovala);
LOG.I (Info_tag, "ovalb:" + ovalb);
LOG.I (Info_tag, "viewnum:" + viewnum);
LOG.I (Info_tag, "Angleperview:" + Angleperview);

if (viewholderlist = = null) {
Viewholderlist = new arraylist<rotatecardviewholder> ();
} else {
Viewholderlist.clear ();
}

float Tmpangle = 270.0f;//The first view at 270 degrees, which is the top position
for (int i = 0; i < Viewnum; ++i) {
int index = i + 1;
View view = Viewlist.get (i);
Adding a slide event listener to a child view
View.setontouchlistener (Mtouchlistener);
Click event Listener to add sub view
View.setonclicklistener (New Itemonclicklistener (index));
Create a rotatecardviewholder for a child view
Rotatecardviewholder holder = new Rotatecardviewholder (view,
Tmpangle, index);
Bundle the holder on the child view and get the holder directly from the sub view
View.settag (holder);
Viewholderlist.add (holder);

Increase the angle of the angleperview to determine the position of the next view
Tmpangle + = Angleperview;
}
The handle view is added to the Rotatecard
Loadviewbysequence ();
}

/**
* Angle of all view rotation Anglediff
*
* @param Anglediff
* Angle of rotation
*/
private void Rotateviewsbyangle (float anglediff) {
If an animation is in progress, no rotation is made
if (set! = null && set.isrunning ()) {
Return
}
Rotate each view
for (Rotatecardviewholder holder:viewholderlist) {
Holder.setangle (Holder.getangle () + Anglediff);
}
Reload view to ensure they are properly occluded
Loadviewbysequence ();
}

/**
* To determine their occlusion relationship by re-adding the view to the Rotatecard after sorting the vew, the more slowly the previous view is added
*/
private void Loadviewbysequence () {
Collections.sort (Viewholderlist, New Rotatecardviewholdercomparator ());
This.removeallviews ();
for (Rotatecardviewholder holder:viewholderlist) {
This.addview (Holder.getview (), viewpparams);
}
}

/**
* Encapsulate some actions on view
*/
public class Rotatecardviewholder {
Private View MView;
private float MAngle;
private int index;

Public Rotatecardviewholder (view view, float angle, int index) {
This.mview = view;
This.mangle = angle;
This.index = index;
Setangle (angle);
}

/**
* Set Location and size
*/
public void Resetpositionandscale () {
Set size
float Anglediff = GETANGLEDIFFWITH90 ();
Float scale = (float) ((1.0 * anglediff/180) * 0.75 + 0.25);
Mview.setscalex (scale);
Mview.setscaley (scale);

Set Location
float x = (float) (Ovala * Math.Cos (mangle/180.0 * Math.PI)
+ PARENTWIDTH/2-VIEWWIDTH/2);
Float y = (float) (PARENTHEIGHT/2-Ovalb
* Math.sin (mangle/180.0 * math.pi)-VIEWHEIGHT/2);
Mview.setx (x);
Mview.sety (y);
}

/**
* Set the view angle while changing the size and position of his display
*
* @param angle
* Angle of view
*/
public void Setangle (float angle) {
Guarantee the mangle between 0~360
MAngle = angle;
while (MAngle < 0 | | mAngle > 360) {
if (MAngle < 0) {
MAngle = (mAngle + 360)% 360;
} else {
MAngle = mAngle% 360;
}
}
Resetpositionandscale ();
}

/**
* Get angle of view
*
* Angle of @return View
*/
public float Getangle () {
return mAngle;
}

/**
* Get the first sequence number of a view
*
* Number of @return view
*/
public int GetIndex () {
return index;
}

/**
* Get an instance of view
*
* Example of @return view
*/
Public View GetView () {
return mView;
}

/**
* Gets the degree of difference between the current position of the view and the 90 degree position
*
* @return degrees of difference from 90 degrees
*/
public float getAngleDiffWith90 () {
float Tmpangle = mAngle > 270? Mangle-360:mangle;
float Anglediff = Math.Abs (tmpAngle-90);
return Anglediff;
}

/**
* Gets the degree of difference between the current position of the view and the 270 degree position
*
* @return degrees of difference from 270 degrees
*/
public float getAngleDiffWith270 () {
float Tmpangle = MAngle < 90? MAngle + 360:mangle;
float Anglediff = Math.Abs (tmpAngle-270);
return Anglediff;
}

}

/**
* Comparator, which is used to sort the view in the order of 270 degrees more
*
*/
public class Rotatecardviewholdercomparator implements
comparator<rotatecardviewholder> {

@Override
public int Compare (Rotatecardviewholder A, Rotatecardviewholder b) {
TODO auto-generated Method Stub
return a.getanglediffwith270 () > b.getanglediffwith270 ()? -1:1;

}
}

Private float LASTX, nowx;//the x-coordinate position of the last finger and the x-coordinate position of the current finger
Private Velocitytracker vtracker;//to monitor finger slip utilization
Private Animatorset set;//Motion album
Private Boolean justcancelanimation = false;//has just clicked the screen so that the in-progress animation is canceled, the Click event that was used to cancel the animation of the colleague

@Override
public boolean dispatchtouchevent (Motionevent event) {
int action = Event.getaction ();
Switch (action) {
Case Motionevent.action_down: {
If the animation is in progress, cancel the animation
if (set! = null && set.isrunning ()) {
Set.cancel ();
set = NULL;
Justcancelanimation = true;
}
Get an instance of Velocitytracker
Vtracker = Velocitytracker.obtain ();
Record Lastx
LASTX = Event.getx ();
}
Break
Case Motionevent.action_move: {
Justcancelanimation = false;
Send the action to Vtracker.
Vtracker.addmovement (event);
Record Nowx
NOWX = Event.getx ();
}
Break
Case MOTIONEVENT.ACTION_UP: {
if (justcancelanimation) {
Justcancelanimation = false;
Return true;//used to cancel a click event
}
Set the calculation unit to 1 seconds
Vtracker.computecurrentvelocity (1000);
Gets the number of pixels across the x-axis for 1 seconds
float xspeed = vtracker.getxvelocity ();
The activity is too fast, then perform the animation, let the Rotatecard rotate for a while to stop
if (Math.Abs (xspeed) > 800.0f) {
and the angle to rotate.
float Anglediff = XSPEED/10;
And the time to rotate.
int duration = (int) (Math.Abs (ANGLEDIFF)/180 * 1000);

Set up a motion album
set = new Animatorset ();
Valueanimator animation = Valueanimator.offloat (0f, 1f)
. setduration (duration);
Animation.addupdatelistener (New Animatorupdatelistener () {

@Override
public void Onanimationupdate (Valueanimator animation) {
TODO auto-generated Method Stub
Loadviewbysequence ();
}

});
Set.play (animation);
for (Rotatecardviewholder _holder:viewholderlist) {
Objectanimator OA = objectanimator.offloat (_holder,
"Angle", _holder.getangle (),
_holder.getangle () + Anglediff). Setduration (
Duration);
Oa.setinterpolator (New Decelerateinterpolator ());
Set.play (OA). with (animation);
}
Start Animation Collection
Set.start ();
}
}
Break
}
Return Super.dispatchtouchevent (event);
}

Private class Rotatecardontouchlistener implements Ontouchlistener {

@Override
public boolean OnTouch (View V, motionevent event) {
TODO auto-generated Method Stub
int action = Event.getaction ();
Switch (action) {
Case Motionevent.action_down: {

}
Break
Case Motionevent.action_move: {
The degree of rotation required for this finger slide
float Anglediff = (nowx-lastx) * ANGLEOFFSET;
Angle of rotation Anglediff
Rotateviewsbyangle (Anglediff);
Record Lastx
LASTX = nowx;
}
Break
Case MOTIONEVENT.ACTION_UP: {

}
Break
}

if (v instanceof rotatecard) {
If the position of the finger is Rotatecard, return true to let the event continue to pass to Rotatecard
return true;
} else {
If the position of the finger is a child view, return False to allow the Click event of the child view to respond
return false;
}
}
}

public class Itemonclicklistener implements Onclicklistener {

private int index;

public itemonclicklistener (int index) {
This.index = index;
}

/**
* * Turn the clicked view to the front of the rotation
*/
@Override
public void OnClick (View v) {
TODO auto-generated Method Stub
Final View TView = v;
Final Rotatecardviewholder holder = (rotatecardviewholder) v
. Gettag ();
float angle = Holder.getangle ();
Degree of rotation required
float Anglediff = Angle >= 0.0f && angle <= 90.0f? -90.0f-angle
: 270.0f-angle;
Whether the child executes the Click event of the view (if the view is clicked in front, then the Click event is executed after the rotation)
Final Boolean PerformClick = Math.Abs (Anglediff) < 45.0f;
int duration = (int) (Math.Abs (ANGLEDIFF)/180 * 1000);

Initial Motion Album
set = new Animatorset ();
Valueanimator animation = Valueanimator.offloat (0f, 1f)
. setduration (duration);
Animation.addupdatelistener (New Animatorupdatelistener () {

@Override
public void Onanimationupdate (Valueanimator animation) {
TODO auto-generated Method Stub
Loadviewbysequence ();
}

});
Set.play (animation);
if (PerformClick) {
Objectanimator AA = Objectanimator.offloat (TView, "Alpha",
1.0f, 0.5f, 1.0f). Setduration (800);
Objectanimator SaX = objectanimator.offloat (TView, "ScaleX",
1.0f, 1.5f, 1.0f). Setduration (800);
Objectanimator SaY = objectanimator.offloat (TView, "ScaleY",
1.0f, 1.5f, 1.0f). Setduration (800);
Set.play (AA). with (animation);
Set.play (SaX). with (animation);
Set.play (SaY). with (animation);
}
for (Rotatecardviewholder _holder:viewholderlist) {
Objectanimator OA = objectanimator.offloat (_holder, "angle",
_holder.getangle (), _holder.getangle () + Anglediff)
. setduration (duration);
Oa.setinterpolator (New Decelerateinterpolator ());
Set.play (OA). with (animation);
}
Set.addlistener (New Animatorlisteneradapter () {
@Override
public void Onanimationend (Animator animation) {
TODO auto-generated Method Stub
if (Monitemclicklistener! = null && PerformClick) {
Perform external settings for click events
Monitemclicklistener.onitemclicklistener (TView, index);
}
}

@Override
public void Onanimationcancel (Animator animation) {
TODO auto-generated Method Stub
Tview.setalpha (1.0f);
Holder.resetpositionandscale ();
}
});
Set.start ();
}
}

/**
* Sub View Click event Listener Onitemclicklistener
*
* Rotatecard internal need to handle the child Vew click events, Onitemclicklistener Listener for external code use
*/
Public interface Onitemclicklistener {
public void Onitemclicklistener (view view, int index);
}

Private Onitemclicklistener Monitemclicklistener;

/**
* Add Sub View Click event Listener
*
* @param onitemclicklistener
*/
public void Setonitemclicklistener (Onitemclicklistener onitemclicklistener) {
This.monitemclicklistener = Onitemclicklistener;
}
}

2. Layout reference:

<us.eiyou.financial_management_service. Rotatecard
Android:id= "@+id/card"
Android:layout_width= "Match_parent"
android:layout_height= "400DP"
Android:layout_alignparentleft= "true"
Android:layout_centervertical= "true"/>

3. Activity Call:

/**
* Rotate View
*/
Rotatecard Card;
arraylist<view> views;

/**
* Rotate View
*/
Card = (Rotatecard) Findviewbyid (R.id.card);
views = new arraylist<view> ();

img = new ImageView (Getapplicationcontext ());
Img.setimageresource (R.DRAWABLE.HUILV);
Views.add (IMG);

img = new ImageView (Getapplicationcontext ());
Img.setimageresource (R.drawable.cunkuan);
Views.add (IMG);

img = new ImageView (Getapplicationcontext ());
Img.setimageresource (R.drawable.fangdai);
Views.add (IMG);

menu selection for rotary effects

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.