Android game details page (2)

Source: Internet
Author: User

Android game details page (2)
Preface

Through the analysis in the previous article, I have basically understood the idea of the game details page. This article mainly aims to achieve the basic effect of the page.

Page Layout

Based on the analysis in the previous article, we know that the game details page is implemented through three different layers of layout overlays. To achieve this level structure, we need to use RelativeLayout.
The three View levels are: Introducing the head layout of the game introduction, details of the game details interface, and toolbar.

Introduce the head layout of the game introduction:


In the red circle, we will introduce the head layout of the game.

Layout_game_detail_head.xml


  
      
       
        
             
       
        
        
        
        
        
        
        
        
         
          
         
        
       
      
         
         
      
     
    
   
  
Displays the content layout of various game details


The yellow circle shows the layout of game dating content.

Layout_content.xml


  
      
           
        
    
   
  
ToolBar Layout

Layout_bar.xml


  
      
       
        
     
    
   
  
Homepage Layout

Activity_main.xml


  
          
       
        
     
    
   
  

These are some common view la S. By placing different la s in RelativeLayout, you can achieve complex interface effects.

Implementation of content interface movement

Observe the game content of dangle and find that there are three statuses of moving the content interface:
1. Status at the top

2. Intermediate status

3. Bottom status

When it is in the top state, in figure 1, the game introduction in the Red Circle is removed from the layout, and the tab is fixed under toobar.
2. toolba is completely transparent when it is in the intermediate state, and the UI of the game details is moved to the center, while the toolba is in the bottom state, as the layout of various game information is moved out of the interface, the game profile layout is fixed at the bottom of the screen.

In the process of moving, we need several parameters to define the location of several States in the moving layout:

 mTopL = -mHeadH + mBarH; mCenterL = Util.dp2px(150); mBottomL = mScreenH - mStateBarH - mNBarH - mHeadH + mBarH;
MHeadH displays the View of the Game Information's header (the height of the View in the red circle)
Authorization + 2yA0KPHA + 0sa2r7K8vta1xMq1z9a0 + sLryOfPwjo8L3A + DQo8cHJlIGNsYXNzPQ = "brush: java;"> /** Use gestures to control the movement of GameContentView */class SimpleGestureAction extends GestureDetector. else {@ Override public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {if (mRawY <= mTopL & distanceY> 0) {mRawY = mTopL; return true;} if (mRawY> = mBottomL & distanceY <0) {mRawY = mBottomL; return true;} mRawY-= distanceY; if (mRawY <mCenterL) {a + = DistanceY <0? -0.03: 0.03; if (a <0.0f) {a = 0.0f;} else if (a> 1.0f) {a = 1.0f ;}} else {a = 0.0f ;} if (mRawY <= mTopL) {mRawY = mTopL; a = 1.0f; mBarBg. setAlpha (a); mTemp. setAlpha (a);} mContent. setTranslationY (mRawY); if (mRawY> = mCenterL + mBarH) {rotationBanner (true);} return true ;}@ Override public boolean onTouchEvent (MotionEvent event) {switch (event. getAction () {case MotionEvent. ACTION_UP: if (mRawY <=-mStateBarH) {toTop ();} else if (-mStateBarH <mRawY & mRawY <= mCenterL + (mBarH <1 ))) {toCenter ();} else if (mCenterL + (mBarH <1) <= mRawY) {toBottom () ;}return true; default: if (0 <= a & a <= 1.0f) {mBarBg. setAlpha (a); mTemp. setAlpha (a);} mDetector. onTouchEvent (event); return super. onTouchEvent (event) ;}}/*** return to the top */private void toTop () {AnimatorSet set = new AnimatorSet (); ObjectAnimator animator = ObjectAnimator. ofFloat (mContent, "translationY", mRawY, mTopL); ObjectAnimator alpha = ObjectAnimator. ofFloat (mBarBg, "alpha", a, 1.0f); ObjectAnimator alpha1 = ObjectAnimator. ofFloat (mTemp, "alpha", a, 1.0f); set. setduration( 500); set. play (animator ). with (alpha ). with (alpha1); set. start (); mRawY = mTopL; // mCurrentState = STATE_TOP; a = 1.0f; mBarBg. setAlpha (a); mTemp. setAlpha (a); // showBottomBar (true);}/*** return to the center */private void toCenter () {ObjectAnimator animator = ObjectAnimator. ofFloat (mContent, "translationY", mRawY, mCenterL); animator. setDuration (500); animator. start (); mRawY = mCenterL; a = 0.0f; mBarBg. setAlpha (a); mTemp. setAlpha (a); mCurrentState = STATE_CENTER; rotationBanner (false); // showBottomBar (true);}/*** to the bottom */private void toBottom () {ObjectAnimator animator = ObjectAnimator. ofFloat (mContent, "translationY", mRawY, mBottomL); animator. setDuration (500); animator. start (); mRawY = mBottomL; a = 0.0f; mBarBg. setAlpha (a); mTemp. setAlpha (a); mCurrentState = STATE_BOTTOM; rotationBanner (true );

The above Code uses gestures to dynamically set the Y axis coordinates on the interface. There is nothing to say here, and it is a basic gesture operation.
At the same time, when moving to a certain position but not yet reaching the position we specified, we need to perform the rebound processing, and the rebound operation is implemented in the onTouchEvent overload method. When we detect that the finger is released, we can compare the current position with the defined interval to determine the status of the View.
* ToTop () is restored to the top state.
* The toCenter () is restored to the intermediate state.
* ToBottom () is restored to the bottom state.

Game rotation implementation

Moving has been implemented. Continue to observe the original interface. When the mobile layout moves from the intermediate state to the bottom state, the game in the bottom layer will rotate, restore the original state when it returns from the bottom to the middle.
The Code is as follows:
Displays the Fragment of the game.

Public class ScreenshotFragment extends BaseFragment {@ InjectView (R. id. img_banner) ImageView mBannerImg; private BannerEntity mEntity; private boolean isCanClick = false; private HandlerThread mHt; private RotationHandler mHandler; private handler () {} public static worker newInstance (BannerEntity entity) {ScreenshotFragment fragment = new ScreenshotFragment (); Bundle B = New Bundle (); B. putParcelable ("entity", entity); fragment. setArguments (B); return fragment;} @ Override protected void init (Bundle savedInstanceState) {mEntity = getArguments (). getParcelable ("entity"); mBannerImg. setScaleType (ImageView. scaleType. FIT_XY); setUpData (mEntity); mRootView. setOnClickListener (new View. onClickListener () {@ Override public void onClick (View v) {if (! IsCanClick) {return ;}}); mHt = new HandlerThread ("rotation_ht", Process. THREAD_PRIORITY_DEFAULT); mHt. start (); mHandler = new RotationHandler (mHt. getlogoff ();}/*** get ImageView */public ImageView getBannerImg () {return mBannerImg;}/*** set whether to click */public void setCanClick (boolean isCanClick) {this. isCanClick = isCanClick;}/*** set data ** @ param entity */private void setUpData (BannerEnt Ity entity) {mBannerImg. setTag (null); Glide. with (getContext ()). load (entity. getImgUrl ()). diskCacheStrategy (DiskCacheStrategy. ALL ). into (mBannerImg);}/*** set image */public void setDrawable (@ DrawableRes int drawable) {if (mBannerImg! = Null) {mBannerImg. setImageResource (drawable);}/*** update data */public void update (BannerEntity entity) {mEntity = entity; setUpData (entity );} /*** set Banner height ** @ param height */public void setBannerHeight (int height) {if (mBannerImg = null) {return;} ViewGroup. layoutParams lp = mBannerImg. getLayoutParams (); lp. height = height; mBannerImg. setLayoutParams (lp) ;}@ Override public void onD Estroy () {super. onDestroy (); if (mHt! = Null) {mHt. quit () ;}}/*** rotate the image ** @ param rotation determines whether to rotate */public void setRotation (boolean rotation) {setRotation (rotation, false );} /*** rotate the image ** @ param useAnim use an animation */public void setRotation (boolean rotation, boolean useAnim) {mHandler. obtainMessage (rotation? 0: 1, useAnim ). sendToTarget () ;}@ Override protected int setLayoutId () {return R. layout. fragment_banner;} private class RotationHandler extends Handler {public RotationHandler (Looper loler) {super (loation) ;}@ Override public void handleMessage (Message msg) {super. handleMessage (msg); if (mBannerImg = null) {return;} final int what = msg. what; final boolean useAnim = (boolean) msg. obj; mBannerImg. post (new Runnable () {@ Override public void run () {if (what = 0) {rotation (mBannerImg, useAnim);} else if (what = 1) {resumeRotation (mBannerImg, useAnim) ;}});}/*** rotate ** @ param img */private void rotation (ImageView img, boolean useAnim) {int w = Util. get1_wwidth (getActivity (), h = Util. getWindowHeight (getActivity (); int iw = img. getMeasuredWidth (), ih = img. getMeasuredHeight (); if (useAnim) {ObjectAnimator move = ObjectAnimator. ofFloat (img, "translationY", 0, (h-ih)/2f); move. setDuration (400); ObjectAnimator scaleX = ObjectAnimator. ofFloat (img, "scaleX", 1.0f, (float) h/iw); ObjectAnimator scaleY = ObjectAnimator. ofFloat (img, "scaleY", 1.0f, (float) w/ih); ObjectAnimator rotation = ObjectAnimator. ofFloat (img, "rotation", 0f, 90f); AnimatorSet set = new AnimatorSet (); set. play (scaleX ). with (scaleY ). with (rotation ). with (move); set. setduration( 600); set. start ();} else {img. setTranslationY (h-ih)/2f); img. setScaleX (float) h/iw); img. setScaleY (float) w/ih); img. setRotation (90f);}/*** restore ** @ param img */private void resumeRotation (ImageView img, boolean useAnim) {int w = Util. get1_wwidth (getActivity (), h = Util. getWindowHeight (getActivity (); int iw = img. getMeasuredWidth (), ih = img. getMeasuredHeight (); if (useAnim) {ObjectAnimator move = ObjectAnimator. ofFloat (img, "translationY", (h-ih)/2f, 0); move. setDuration (400); ObjectAnimator scaleX = ObjectAnimator. ofFloat (img, "scaleX", (float) h/iw, 1.0f); ObjectAnimator scaleY = ObjectAnimator. ofFloat (img, "scaleY", (float) w/ih, 1.0f); ObjectAnimator rotation = ObjectAnimator. ofFloat (img, "rotation", 90f, 0f); AnimatorSet set = new AnimatorSet (); set. play (scaleX ). with (scaleY ). with (rotation ). with (move); set. setduration( 600); set. start ();} else {img. setTranslationY (0f); img. setScaleX (1.0f); img. setScaleY (1.0f); img. setRotation (0f );}}}}

ScreenshotFragment is used to display the game interface. When you move a game, you need to perform the following operations: Rotate-> move to the middle-> zoom in. These three operations are animated by attributes, it is easy to implement the animation effect. Note that during the enlargement process, we need to change the width and height of the ImageView so that the ImagView can fully display the enlarged image, at the same time, to ensure the security of UI updates, an asynchronous handler is required to implement its update operations. Here I use a lightweight HandlerThread to implement this asynchronous UI update operation.

/*** Initialize the game ViewPager ** @ return */private void setupGameShotVp (final ViewPager viewPager) {SimpleViewPagerAdapter adapter = new SimpleViewPagerAdapter (getsuppfrfragmentmanager (); List
  
   
Data = getBannerData (); for (BannerEntity entity: data) {adapter. addFrag (ScreenshotFragment. newInstance (entity), "");} viewPager. setAdapter (adapter); viewPager. setOffscreenPageLimit (data. size (); mIndicator. setViewPager (viewPager); // mIndicator. onPageSelected (0); viewPager. addOnPageChangeListener (new ViewPager. onPageChangeListener () {@ Override public void onPageScrolled (int position, float posi TionOffset, int positionOffsetPixels) {mShotVpPosition = position ;}@ Override public void onPageSelected (int position) {}@ Override public void onPageScrollStateChanged (int state ){}}); // set the Banner image height to new Handler (). post (new Runnable () {@ Override public void run () {viewPager. post (new Runnable () {@ Override public void run () {SimpleViewPagerAdapter adapter = (SimpleViewPagerAdapter) mImgVP. g EtAdapter (); int h = (int) getResources (). getDimension (R. dimen. game_detail_head_img_vp_height); for (int I = 0, count = adapter. getCount (); I <count; I ++) {ScreenshotFragment fragment = (ScreenshotFragment) adapter. getItem (I); if (fragment! = Null) {fragment. setBannerHeight (h );}}}});}});}
  

The above is the game initialization code. In the initial position, the height of the ViewPage needs to be fixed. After rotation, you need to set the height of the ViewPage to the height of the screen. In this way, in order to ensure that the game can be fully displayed.


This is basically the result we have achieved. It is getting closer and closer to the game details page of dangle, but it cannot respond to events, the next step is to handle the most challenging sliding conflicts and event distribution. I'm a little excited .....

Related Article

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.