<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)電子書放大鏡效果

          共 5258字,需瀏覽 11分鐘

           ·

          2021-10-24 14:33

          前言


          最近看電子書發(fā)現(xiàn)了一個挺有意思的效果,類似于一個放大鏡,因此就花了點時間實現(xiàn)了一個放大鏡效果的自定義View,電子書里面的效果,如圖所示:



          效果展示


          我寫的效果如下:



          實現(xiàn)原理


          ?

          控件的代碼如下,所有的步驟都加入了注釋,可以直接參考注釋

          public class MagnifierLayout extends FrameLayout {    private Bitmap mBitmap;    private Paint mPaintShadow,mPaintBitmap;    private long mShowTime = 0;//用于判斷顯示放大鏡的時間    private boolean mIsShowMagnifier = false;//是否顯示放大鏡    private Path mPath;//用于裁剪畫布的路徑    private float mShowMagnifierX = 0;//顯示放大鏡的X坐標(biāo)    private float mShowMagnifierY = 0;//顯示放大鏡的Y坐標(biāo)    private float mMagnifierRadius = 200;//放大鏡的半徑    private float mScaleRate = 3f;//放大比例    private Handler mHandler = new Handler();    private Runnable mRunnable = new Runnable() {        @Override        public void run() {            mIsShowMagnifier = true;            postInvalidate();        }    };    public MagnifierLayout(@NonNull Context context) {        this(context,null);    }
          public MagnifierLayout(@NonNull Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); }
          public MagnifierLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); }
          private void init(){ //繪制放大鏡邊緣投影的畫筆 mPaintShadow = new Paint(Paint.ANTI_ALIAS_FLAG); //設(shè)置放大鏡邊緣的投影 mPaintShadow.setShadowLayer(20,6,6, Color.BLACK); //繪制Bitmap的畫筆 mPaintBitmap = new Paint(Paint.ANTI_ALIAS_FLAG); mPath = new Path(); setLayerType(View.LAYER_TYPE_SOFTWARE, null); }
          @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mShowTime = System.currentTimeMillis(); mShowMagnifierX = event.getX() + mMagnifierRadius; mShowMagnifierY = event.getY() - mMagnifierRadius; //如果持續(xù)按超過一秒就顯示放大鏡 startShowMagnifierDelay(); break; case MotionEvent.ACTION_MOVE: //觸摸時間大于1秒才顯示 if(System.currentTimeMillis() - mShowTime >= 1000){ stopShowMagnifier(); mIsShowMagnifier = true; mShowMagnifierX = event.getX() + mMagnifierRadius; mShowMagnifierY = event.getY() - mMagnifierRadius; //重繪 postInvalidate(); } break; case MotionEvent.ACTION_UP: stopShowMagnifier(); mIsShowMagnifier = false; postInvalidate(); break; } return true; }
          private void startShowMagnifierDelay() { stopShowMagnifier(); mHandler.postDelayed(mRunnable,1000); } private void stopShowMagnifier() { mHandler.removeCallbacks(mRunnable); }
          @Override protected void dispatchDraw(Canvas canvas) { if(mIsShowMagnifier){ //創(chuàng)建整個布局內(nèi)容的Bitmap mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); Canvas mCanvas = new Canvas(mBitmap); //將當(dāng)前布局的內(nèi)容繪制在Bitmap上 super.dispatchDraw(mCanvas); //將Bitmap繪制出來(否則頁面是空白,因為上面是用我們自定義的Canvas進(jìn)行繪制的,因此我們還需要用系統(tǒng)的這個進(jìn)行繪制一遍) canvas.drawBitmap(mBitmap,0,0,mPaintBitmap); //繪制出放大鏡邊緣的投影 canvas.drawCircle(mShowMagnifierX,mShowMagnifierY,mMagnifierRadius,mPaintShadow); canvas.save(); //計算出要裁剪畫布的圓形路徑 mPath.reset(); mPath.addCircle(mShowMagnifierX,mShowMagnifierY,mMagnifierRadius, Path.Direction.CW); //將圓形路徑的畫布裁剪出來,這樣繪制的Bitmap就是圓形的 canvas.clipPath(mPath); //繪制當(dāng)前布局的背景顏色,否則放大鏡顯示的背景會是黑色 getBackground().draw(canvas); //根據(jù)縮放的比例計算出裁剪的Bitmap的最小寬高 float magnifierWidthAndHeight = mMagnifierRadius * 2 / mScaleRate; //計算出該裁剪的區(qū)域(就是使手指所在的點在要裁剪的Bitmap的中央),并進(jìn)行邊界值處理(開始裁剪的X點不能小于0和大于Bitmap的寬度,并且X點的位置加上要裁剪的寬度不能大于Bitmap的寬度,Y點也是一樣) int cutX = Math.max((int) (mShowMagnifierX - mMagnifierRadius - magnifierWidthAndHeight / 2), 0); int cutY = Math.min(Math.max((int) (mShowMagnifierY + mMagnifierRadius - magnifierWidthAndHeight / 2),0), mBitmap.getHeight()); //適配邊界值 int cutWidth = magnifierWidthAndHeight + cutX > mBitmap.getWidth() ? mBitmap.getWidth() - cutX : (int)magnifierWidthAndHeight; int cutHeight = magnifierWidthAndHeight + cutY > mBitmap.getHeight() ? mBitmap.getHeight() - cutY : (int)magnifierWidthAndHeight; mBitmap = Bitmap.createBitmap(mBitmap,cutX,cutY,cutWidth,cutHeight); //將裁剪出來的區(qū)域放大 mBitmap = Bitmap.createScaledBitmap(mBitmap,(int) (mBitmap.getWidth() * mScaleRate),(int)(mBitmap.getHeight() * mScaleRate),true); //繪制放大后的Bitmap,由于Bitmap的縮放是從左上點開始的因此還要根據(jù)縮放的比例進(jìn)行相應(yīng)的偏移展示 canvas.drawBitmap(mBitmap,mShowMagnifierX - mMagnifierRadius ,mShowMagnifierY - mMagnifierRadius,mPaintBitmap); canvas.restore(); mBitmap.recycle(); mBitmap = null; }else { super.dispatchDraw(canvas); } }}


          源碼地址:

          https://gitee.com/itfitness/magnifier-layout


          到這里就結(jié)束啦。

          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  日本久久不卡 | av资源站 | www,亚洲黄色片 | 天天操天天摸天天日天天爱 | 天天爽夜夜爽人人爽 |