Android custom View for flipped cards
Generally, a View has only one side, but you can customize a View to achieve the flip effect like a book flip.
Rotating View:
/*** Construct a flip card in two ways ** 1: directly provide a View in a specific naming format * 2: provide two linear la S (front and back) * Created by lip on 2015/4/8. */public class FlipView extends LinearLayout implements View. onClickListener, RotateAnimation. interpolatedTimeListener {private LinearLayout m_first_ll, m_second_ll; private boolean enableRefresh; private LinearLayout view; private View clickView; // The current view private Context context; public FlipView (Context cont Ext) {super (context); this. context = context; // initViews ();} public FlipView (Context context, AttributeSet attrs) {super (context, attrs); this. context = context; // initViews ();}/***/public void initViews () {view = (LinearLayout) inflate (context, R. layout. flip_view, null); m_first_ll = (LinearLayout) view. findViewById (R. id. first_ll); m_second_ll = (LinearLayout) view. findViewById (R. id. second_ll); m_first_l L. setOnClickListener (this); m_second_ll.setOnClickListener (this); addView (view, ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. MATCH_PARENT);}/*** @ param ll1 front * @ param ll2 back */public void addViews (LinearLayout ll1, LinearLayout ll2) {m_first_ll = ll1; m_second_ll = ll2; m_first_ll.setOnClickListener (this); m_second_ll.setOnClickListener (this); addView (m_first_ll, ViewGroup. layoutPa Rams. MATCH_PARENT, ViewGroup. layoutParams. MATCH_PARENT); addView (m_second_ll, ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. MATCH_PARENT);}/*** flag = 0 flip to front * flag = 1 flip to back * @ param flag */public void show (int flag) {enableRefresh = true; rotateAnimation rotateAnim = null; float cX = this. getWidth ()/2.0f; float cY = this. getHeight ()/2.0f; if (flag = 0) rotateAnim = new RotateAnim Ation (cX, cY, RotateAnimation. ROTATE_DECREASE); else if (flag = 1) rotateAnim = new round (cX, cY, RotateAnimation. ROTATE_INCREASE); if (rotateAnim! = Null) {rotateAnim. setInterpolatedTimeListener (this); rotateAnim. setFillAfter (true); this. startAnimation (rotateAnim) ;}@override public void onClick (View v) {Log. d (click:, v. toString (); enableRefresh = true; clickView = v; RotateAnimation rotateAnim = null; float cX = this. getWidth ()/2.0f; float cY = this. getHeight ()/2.0f; if (m_first_ll = v) {rotateAnim = new RotateAnimation (cX, cY, Rotate Animation. ROTATE_INCREASE);} else if (m_second_ll = v) {rotateAnim = new RotateAnimation (cX, cY, RotateAnimation. ROTATE_DECREASE);} if (rotateAnim! = Null) {rotateAnim. setInterpolatedTimeListener (this); rotateAnim. setFillAfter (true); this. startAnimation (rotateAnim) ;}@ Override public void interpolatedTime (float interpolatedTime) {if (latency & interpolatedTime> 0.5f) {setHint (); enableRefresh = false ;}} public void setHint () {if (clickView = m_first_ll) {m_first_ll.setVisibility (View. GONE); m_second_ll.setVisibility (View. VISIBLE);} else if (clickView = m_second_ll) {m_second_ll.setVisibility (View. GONE); m_first_ll.setVisibility (View. VISIBLE );}}}
Let's take a look at the usage:
Public class FlipActivity extends Activity {private FlipView flipView; LinearLayout firstLL, secondLL; LinearLayout root; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); // setContentView (R. layout. activity_flip); initViews ();} private void initViews () {root = (LinearLayout) LayoutInflater. from (this ). inflate (R. layout. activity_flip, null); flipView = (FlipView) root. findViewById (R. id. flip_view);/********** the first method (to actively call initViews) * *********** // firstLL = (LinearLayout) LayoutInflater. from (this ). inflate (R. layout. flip_view1, null); // secondLL = (LinearLayout) LayoutInflater. from (this ). inflate (R. layout. flip_view2, null);/********** second method **************/firstLL = (LinearLayout) root. findViewById (R. id. root_ll1); secondLL = (LinearLayout) root. findViewById (R. id. root_ll2); root. removeView (firstLL); root. removeView (secondLL); flipView. addViews (firstLL, secondLL); setContentView (root );}}
Since a View has two sides, you need to actively set the front and back content.
FlipView. addViews (firstLL, secondLL); the first parameter is the front view, and the second parameter is the opposite view. Both views are linear. I provide two ways to set the front and back sides. If you have a little understanding about the layout, this is actually the same
Rotation tool class (refer to others online ):
When the public class RotateAnimation extends Animation {/** value is true, you can clearly view the Animation rotation direction. */Public static final boolean DEBUG = false;/** the value is displayed along the positive side of the Y axis. If the value is reduced by 1, the animation rotates counterclockwise. */Public static final boolean ROTATE_DECREASE = true;/** it is displayed along the positive side of the Y axis. If the value is reduced by 1, the animation rotates clockwise. */Public static final boolean ROTATE_INCREASE = false;/** maximum depth on the Z axis. */Public static final float DEPTH_Z = 310.0f;/** animation display duration. */Public static final long DURATION = 800l;/** image flip type. */Private final boolean type; private final float centerX; private final float centerY; private Camera camera; public RotateAnimation (float cX, float cY, boolean type) {centerX = cX; centerY = cY; this. type = type; // set the animation DURATION setDuration (DURATION) ;}@ Overridepublic void initialize (int width, int height, int parentWidth, int parentHeight) {// call this method after the constructor and before applyTransformation. Super. initialize (width, height, parentWidth, parentHeight); camera = new Camera ();} @ Overrideprotected void applyTransformation (float interpolatedTime, Transformation transformation) {// interpolatedTime: Specifies the animation progress value, the value range is 0 ~ 1, 0.5 is just half flipped if (listener! = Null) {listener. interpolatedTime (interpolatedTime);} float from = 0.0f, to = 0.0f; if (type = ROTATE_DECREASE) {from = 0.0f; to = 180.0f;} else if (type = ROTATE_INCREASE) {from = 360.0f; to = 180.0f;} // Rotation Angle float degree = from + (to-from) * interpolatedTime; boolean overHalf = (interpolatedTime> 0.5f); if (overHalf) {// if you flip over half of the text, you need to flip 180 degrees to ensure that the number is still readable text rather than mirroring. Degree = degree-180;} // rotation depth float depth = (0.5f-Math. abs (interpolatedTime-0.5f) * DEPTH_Z; final Matrix matrix = transformation. getMatrix (); camera. save (); // depth -- the distance from the screen to camera. translate (0.0f, 0.0f, depth); // rotate on the X axis // camera. rotateX (degree); // rotate camera with the Y axis. rotateY (degree); camera. getMatrix (matrix); camera. restore (); if (DEBUG) {if (overHalf) {matrix. preTranslate (-centerX * 2,-centerY); matrix. pos TTranslate (centerX * 2, centerY) ;}} else {// ensure that the image flip process is always at the center of the component./** preTranslate refers to the translation before setScale, postTranslate refers to the Translation after setScale. Their parameters are the translation distance, * rather than the coordinates of the destination! * Since the scale is centered on (), to align the center of the interface with (), preTranslate (-centerX, *-centerY) is required. After setScale is complete, call postTranslate (centerX, * centerY) and move the image back. The animation effect is that the screen image of the activity is continuously scaled from the center. * Note: centerX and centerY are coordinates of the center of the interface */matrix. preTranslate (-centerX,-centerY); matrix. postTranslate (centerX, centerY) ;}/ ** listens on the animation progress. Content to be updated when the value is over half. */Private InterpolatedTimeListener listener; public void setInterpolatedTimeListener (InterpolatedTimeListener listener) {this. listener = listener;}/** specifies the animation progress listener. */Public static interface InterpolatedTimeListener {public void interpolatedTime (float interpolatedTime );}}