<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android實現(xiàn)3D卡片翻動效果

          共 4743字,需瀏覽 10分鐘

           ·

          2021-07-02 09:07

          作者 |  被代碼淹沒的小伙子
          地址 |  https://www.jianshu.com/p/ee8a37ea736d

          先看效果圖:



          效果:


          1、豎向的Viewpager
          2、3D翻動效果
          3、Glide加載圖片


          實現(xiàn)思路:


          1、Viewpager的豎向滑動這里說下我的實現(xiàn)方式:交換觸摸位置的x,y方向,利用PageTransformer的transformPage()方法,在移動過程中通過translation動態(tài)改變頁面方向?qū)崿F(xiàn)豎向移動。

            
          2、3D翻轉(zhuǎn)效果:也是利用PageTransformer的transformPage()方法,主要通過setRotationX方法,繞X軸旋轉(zhuǎn),這里注意要改變視角距離不然無法實現(xiàn)效果。

          主要代碼:

          /** * Swaps the X and Y coordinates of your touch event. */private MotionEvent swapXY(MotionEvent ev) {    float width = getWidth();    float height = getHeight();
          float newX = (ev.getY() / height) * width; float newY = (ev.getX() / width) * height;
          ev.setLocation(newX, newY);
          return ev;}
          @Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); return intercepted;}


          可以看到這里,重寫了onInterceptTouchEvent,在這里調(diào)用了swapXY方法,這個方法主要是交換了觸摸位置的X,Y坐標,但是代碼可能理解起來有點困難,可以這樣理解:



          Viewpager的默認布局方式如圖所示,也就是只能觸發(fā)你的橫向事件,豎向的滑動并不會影響Viewpager的滑動。


          這里為了使豎向的滑動起效果,可以看到:
          newX = (ev.getY() / height) * width
          這里當你Y軸移動了,通過高寬比,轉(zhuǎn)變成X軸的移動。

          當手指移動距離:
          ev.getY() = height
          對應的X軸就移動了width長度,這也就為后來的實現(xiàn)提供了基礎

          當手指移動距離:
          ev.getX() = width
          (這個其實對后面并沒有影響,因為Viewpager不會觸發(fā)Y軸的移動)
          private class VerticalPageTransformer implements ViewPager.PageTransformer {
          @Override public void transformPage(View view, float position) { if (position <= 0) { view.setAlpha(1); view.setTranslationY((float) (-view.getHeight() * (1 - Math.pow(0.9f, -position)))); //設置縮放中點 view.setPivotX(view.getWidth() / 2f); view.setPivotY(view.getHeight() / 2f); //設置縮放的比例 此處設置兩個相鄰的卡片的縮放比率為0.9f float Scale = (float) Math.pow(0.9f, -position); if (Scale > 0.7f) { view.setScaleX(Scale); view.setScaleY(Scale); } else { view.setAlpha(0); } } else {//(0,++) view.setPivotY(view.getHeight()); setCameraDistance(view); view.setRotationX(180 * -position); view.setAlpha(1 - position); }        view.setTranslationX(view.getWidth() * -position); }}


          重寫的PageTransformer的transformPage的方法,這里重點要理解position參數(shù)。這里我畫了個圖方便理解,由圖可見:





          初始時,前三張的position分別為0,1,2。
          向左滑動一頁:前三張的position分別為-1,0,1
          再向左滑一頁:前三張的position分別為-2,-1,0
          所以可以得到position的變化范圍,當前頁顯示的position為0,當前頁左邊的顯示的<0,當前頁右邊的顯示的>0。
          這里我將當前頁設置為最后一頁(總量為8),那么顯示的position分別為-7,-6...-2,-1,0


          現(xiàn)在來一步一步實現(xiàn)


          1.實現(xiàn)X坐標相同


          view.setTranslationX(view.getWidth() * -position);


          現(xiàn)在要將布局顯示成豎向排列,所以很容易想到把每個View的X坐標+width*-position

          這時候可以想到,所有的頁面都重疊在一起,位置在position=0的地方。


          2.實現(xiàn)Y坐標逐減


          現(xiàn)在則需要將頁面的Y坐標,分別向上移動一點距離,
          這里我通過0.9的冪函數(shù)來實現(xiàn)錯開。
          view.setTranslationY((float) (-view.getHeight() * (1 - Math.pow(0.9f, -position))));


          position=0:對應的y
          position=-1:要上移一點,y-height(1-0.9) = y-height0.1
          position=-2:再上移一點,y-height(1-0.90.9) = y-height*0.19
          ...以此類推


          3.實現(xiàn)逐層縮小


          這塊應該就比較好實現(xiàn)了,現(xiàn)在position=0,-1,-2,-3,...,-7(我是設第一頁顯示末頁,倒著來)
          //設置縮放中點                view.setPivotX(view.getWidth() / 2f);                view.setPivotY(view.getHeight() / 2f);                //設置縮放的比例 此處設置兩個相鄰的卡片的縮放比率為0.9f                float Scale = (float) Math.pow(0.9f, -position);                view.setScaleX(Scale);                view.setScaleY(Scale);


          可以看到,代碼還是比較好理解的,前兩句設置縮放中點,后面就是設置縮放比例為0.9的冪函數(shù)
          position=0:對應Scale = 1
          position=-1:Scale=0.9
          position=-2:Scale=0.9*0.9=0.81


          4.實現(xiàn)3D繞軸旋轉(zhuǎn)

          view.setPivotY(view.getHeight());setCameraDistance(view);                view.setRotationX(180 * -position);    /**     * 改變視角距離, 貼近屏幕     */    private void setCameraDistance(View view) {        int distance = 10000;        float scale = getResources().getDisplayMetrics().density * distance;        view.setCameraDistance(scale);    }


          首先根據(jù)我們要實現(xiàn)的效果,可以發(fā)現(xiàn)我們是繞圖片的下邊線旋轉(zhuǎn)的,所以我們首先設軸為y=height
          view.setPivotY(view.getHeight());


          setCameraDistance()這個函數(shù)我們等會說
          這里我們軸確定了好就要確定我們的旋轉(zhuǎn)的角度,根據(jù)效果,我們發(fā)現(xiàn),我們旋轉(zhuǎn)的角度是[0,-180],而position的變化范圍是[0,1],所以代碼就很好理解了
          view.setRotationX(180 * -position);


          一開始我以為這樣就實現(xiàn)了效果,但是運行效果會發(fā)現(xiàn)很奇怪


          最后通過網(wǎng)上搜尋發(fā)現(xiàn)原因就是需要使用這個函數(shù),改變視角距離,貼近屏幕,看起來才正確。
          /**     * 改變視角距離, 貼近屏幕     */    private void setCameraDistance(View view) {        int distance = 10000;        float scale = getResources().getDisplayMetrics().density * distance;        view.setCameraDistance(scale);    }


          5.透明度變化


          這塊就很好理解了,我將position分為了兩個區(qū)段,(負無窮,0),[0,正無窮)
          (負無窮,0) alpha =1
          [0,1] alpha =1-position逐漸透明
          [1,正無窮)alpha <=0透明


          6.設置顯示頁數(shù)


          這里可以發(fā)現(xiàn),實現(xiàn)出來的效果,后面的頁會一直顯示在后面,看起來密集恐懼癥+強迫癥有木有
           if (Scale > 0.7f) {                    view.setScaleX(Scale);                    view.setScaleY(Scale);                } else {                    view.setAlpha(0);                }


          所以我在這設置了一下,當縮放值小于0.7時,就讓它隱藏。


          源碼地址:
          https://github.com/DrownCoder/GlideStudy

          到這里就結(jié)束啦
          瀏覽 92
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲性爱视频网站 | 爽妇综合网 | 蒙古一级黄片 | 可以看靠逼视频的网址 | 欧美一級黃色A片免費看 |