欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

android 自定義ScrollView實現(xiàn)背景圖片伸縮的實現(xiàn)代碼及思路

 更新時間:2013年05月22日 15:38:01   作者:  
本文純屬個人見解,是對前面學(xué)習(xí)的總結(jié),如有描述不正確的地方還請高手指正~,首先還是按照通例給大家看下示例.

  

  用過多米音樂的都市知道, 這個UI可以上下滑動,作用嘛---無聊中可以劃劃解解悶,這被錘子公司老羅稱謂為“情懷”,其實叫“情味”更合適。嘿嘿.如今挪動互聯(lián)網(wǎng)開展這么迅速,市場上已不再是那早期隨便敲個APP放上架就能具有幾十萬用戶的階段了.近來蘋果公司,為了怕android下載量趕超蘋果商店,大勢宣稱:(第 500 億個下載應(yīng)用的用戶就能夠獲得 10,000 美元的 iTunes 禮品卡,除此之外,緊隨第 500 億以后的前 50 名用戶也可以獲得 500 美元的禮品卡.至于挪動開展趨勢,我想搞挪動IT的人心里都比擬清楚,扯遠了).其實應(yīng)用UI殊效是應(yīng)用中很大的一部分,如果同樣功能的兩款軟件,一個功能好點如“網(wǎng)易新聞”,另外一個略微差點如“新浪新聞”,用戶的你毫無疑難確定會選擇網(wǎng)易客戶端.總結(jié)就是“操作性”對于產(chǎn)品起著至關(guān)重要的因素.

    接下來我們看下如何實現(xiàn),首先聲明,這個實現(xiàn)的方式不是很好,我這里只是提出一個解決方案,大家可以根據(jù)自己的想法進行創(chuàng)新.

    道理:RelativeLayout+自定義ScrollView.

    我們大致看下布局結(jié)構(gòu)如圖:

  

其實也沒什么技術(shù)含量,我簡單介紹下:紅色代表的是背景照片,綠色的代表自定義ScrollView,粉色是代表你要編輯的透明區(qū)域.也不過多解釋,想必大家都明確,我們還是來看代碼吧。

由于屬于情懷殊效(沒有具體的回調(diào)事件要求),那么就沒有必要自定義監(jiān)聽,回調(diào)處理,我直接把要處理的UI注入到自定義控件中,這樣她方便我也方便.

在此說明一下,前面部分實現(xiàn)中有誤,但是也希望您仔細品讀,相信您必定可以學(xué)到一些知識的。

首先我們將背景圖片和頂部線條注入到該控件中。接著我們看onTouchEvent事件,因為至始至終都是她在起作用.

   

復(fù)制代碼 代碼如下:

    /***
  * 觸摸事件
  *
  * @param ev
  */
 public void commOnTouchEvent(MotionEvent ev) {
  int action = ev.getAction();
  switch (action) {
  case MotionEvent.ACTION_DOWN:
   initTouchY = ev.getY();

   current_Top = initTop = imageView.getTop();
   current_Bottom = initBottom = imageView.getBottom();
   lineUp_current_Top = line_up_top = line_up.getTop();
   lineUp_current_Bottom = line_up_bottom = line_up.getBottom();
   break;
  case MotionEvent.ACTION_UP:
   /** 回縮動畫 **/
   if (isNeedAnimation()) {
    animation();
   }

   isMoveing = false;
   touchY = 0;// 手指松開要歸0.

   break;

  /***
   * 消除出第一次挪動計算,因為第一次無法得知deltaY的高度, 然而我們也要進行初始化,就是第一次挪動的時候讓滑動距離歸0.
   * 以后記載精確了就正常執(zhí)行.
   */
  case MotionEvent.ACTION_MOVE:

   Log.e(TAG, "isMoveing=" + isMoveing);

   touchY = ev.getY();

   float deltaY = touchY - initTouchY;// 滑動距離

   Log.e(TAG, "deltaY=" + deltaY);

   /** 過濾: **/
   if (deltaY < 0 && inner.getTop() <= 0) {
    return;
   }

   // 當滾動到最上或者最下時就不會再滾動,這時挪動布局
   isNeedMove();

   if (isMoveing) {
    // 初始化頭部矩形
    if (normal.isEmpty()) {
     // 保存正常的布局位置
     normal.set(inner.getLeft(), inner.getTop(),
       inner.getRight(), inner.getBottom());
    }
    // 挪動布局(手勢挪動的1/3)
    float inner_move_H = deltaY / 5;
    inner.layout(normal.left, (int) (normal.top + inner_move_H),
      normal.right, (int) (normal.bottom + inner_move_H));

    /** image_bg **/
    float image_move_H = deltaY / 10;
    current_Top = (int) (initTop + image_move_H);
    current_Bottom = (int) (initBottom + image_move_H);
    imageView.layout(imageView.getLeft(), current_Top,
      imageView.getRight(), current_Bottom);

    /** line_up **/
    float line_up_H = inner_move_H;
    lineUp_current_Top = (int) (line_up_top + inner_move_H);
    lineUp_current_Bottom = (int) (line_up_bottom + inner_move_H);
    line_up.layout(line_up.getLeft(), lineUp_current_Top,
      line_up.getRight(), lineUp_current_Bottom);
   }
   break;

  default:
   break;

  }
 }


簡單說明:

MotionEvent.ACTION_DOWN:觸摸摁下獲得相應(yīng)的坐標.

MotionEvent.ACTION_MOVE:

里面有個方法isNeedMove。作用:我們滑動的是ScrollView自身呢,還是我們自己模擬的那種滑動.

復(fù)制代碼 代碼如下:

/***
  * 是不是須要挪動布局 inner.getMeasuredHeight():獲得的是控件的總高度
  *
  * getHeight():獲得的是屏幕的高度
  *
  * @return
  */
 public void isNeedMove() {
  int offset = inner.getMeasuredHeight() - getHeight();
  int scrollY = getScrollY();
  // 如果ScrollView的子View們沒有超越一屏幕則scrollY == 0,直接返回true,
  //如果ScrollView的子View們超越了一屏幕則 getScrollY()==offset說明滑到了ScrollView的低端.這時候才返回true.
  if (scrollY == 0 || scrollY == offset) {
   isMoveing = true;
  }
 }

這里面用到最多的就是:view.layout(l, t, r, b);作用很簡單不解釋。詳情請參看源碼.

MotionEvent.ACTION_UP:就是做些善后操作,主要看animation方法.

復(fù)制代碼 代碼如下:

/***
  * 回縮動畫
  */
 public void animation() {

  TranslateAnimation image_Anim = new TranslateAnimation(0, 0,
    Math.abs(initTop - current_Top), 0);
  image_Anim.setDuration(200);
  imageView.startAnimation(image_Anim);

  imageView.layout(imageView.getLeft(), (int) initTop,
    imageView.getRight(), (int) initBottom);

  // 開啟挪動動畫
  TranslateAnimation inner_Anim = new TranslateAnimation(0, 0,
    inner.getTop(), normal.top);
  inner_Anim.setDuration(200);
  inner.startAnimation(inner_Anim);
  inner.layout(normal.left, normal.top, normal.right, normal.bottom);

  /** line_up **/
  TranslateAnimation line_up_Anim = new TranslateAnimation(0, 0,
    Math.abs(line_up_top - lineUp_current_Top), 0);
  line_up_Anim.setDuration(200);
  line_up.startAnimation(line_up_Anim);
  line_up.layout(line_up.getLeft(), line_up_top, line_up.getRight(),
    line_up_bottom);

  normal.setEmpty();

  /** 動畫執(zhí)行 **/
  if (current_Top > initTop + 50 && turnListener != null)
   turnListener.onTurn();

 }

    這里我要簡單說明一下,因為我在這里栽了有些時光.

    比如:我們的背景圖片本來坐標為:(0,-190,800,300),隨著手勢挪動到(0,-100,800,390)挪動了90像素,那么我們的TranslateAnimation應(yīng)當如何寫呢?我之前總以為不就是末尾坐標指向初始坐標不就完了,結(jié)果你會發(fā)明,動畫基本不起作用而是一閃而過。原因呢,動畫參數(shù)弗成以為正數(shù).或許因為動畫是以(0,0)為參照物吧.因此要把動畫寫成TranslateAnimation line_up_Anim = new TranslateAnimation(0, 0,Math.abs(-190- (-100)), 0);這樣我們所須要的動畫效果就實現(xiàn)了.

    但是新的問題又出現(xiàn)了:

    當你下拉到必定狀態(tài)后然后漸漸向上挪動,會發(fā)明挪動的很快(沒有回縮的反響),而挪動到最頂部的時候突然又出現(xiàn)反彈效果。這個效果固然不是我們所須要的那種。我們所須要的效果是:下拉到必定水平,然后反過來上拉的時候要漸漸的挪動回到原點(中央位置)停止。如果是上拉的話,不要出現(xiàn)反彈效果,如果是下拉松開的話,出現(xiàn)反彈效果。

    描述的有點亂,如果想知道具體效果的話,我提議你應(yīng)用下papa,其實海內(nèi)這些比擬優(yōu)秀的應(yīng)用UI都是抄襲國外的,如果你用facebook的話,就會發(fā)明,怎么啪啪的個人頁面長的也忒像facebook了。請看下圖:

 

    嘿嘿,不好意思,跑題了,針對上面出現(xiàn)的問題,我簡單說明一下.

    首先,比如我們手勢下拉了50像素,其實是使得自定義ScrollView的孩子也就是LinearLayout這個控件的top為50,而這個時候的getScrollY()的值仍為0,但是如果此時你停止下拉反而向上拉取的話,那么此時的getScrollY()會從0開始逐步增大,當我們挪動到頂部也就是將ScrollView挪動到最底部,此時的isMoveing為true,所以你繼承上拉的話會出現(xiàn)反彈效果。

    這個問題要如何解決呢,其實也不難,但是我糾結(jié)了好長時光,也走了很多多少彎路。在這里說明一下我的瞎跑路段以及疑難:當時我就想,getScrollY()這么不聽話,我何必非要對ScrollView的孩子進行操作呢,為何直接不對本控件執(zhí)行l(wèi)ayout(l,t,r,b)呢,后來就照著這個邏輯進行update,終于更改了差不多了,糾結(jié)了問題再次出現(xiàn),在你下拉的時候?qū)crollView本身執(zhí)行l(wèi)ayout(l,t,r,b)這個方法可以實現(xiàn)反彈效果,但是此時你確無法進行滑動了,就是ScrollView本身的滑動無緣無故的被禁止掉了.我懷疑是layout的時候參數(shù)弄錯了。,后來仔細修改了下發(fā)明還是弗成以滑動,然后google了半天也杳無音訊,最后固然放棄,又回到了原點。接著揣摩。。。算是功夫不負有心人吧,最終想到了解決方案,希望對您有幫助。

    還拿上面說到的那短話,比如我們手勢下拉了50像素,那么此時touch的距離也就是50像素,如果此時我們反向上拉的話,同樣是須要50像素回到最初的位置。說到這里我想大家都明確了。(首先我們要將操作離開,分為UP,DOWN,如果是DOWN的話,那么在下拉后執(zhí)行上拉的時候我們禁用掉自定義控件的滑動,而是通過手勢執(zhí)行l(wèi)ayout執(zhí)行這50像素.)

    上面我們看部分代碼:

   

復(fù)制代碼 代碼如下:

    /**對于初次Touch操作要判斷方位:UP OR DOWN**/
   if (deltaY < 0 && state == state.NOMAL) {
    state = State.UP;
   } else if (deltaY > 0 && state == state.NOMAL) {
    state = State.DOWN;
   }


   if (state == State.UP) {
    deltaY = deltaY < 0 ? deltaY : 0;
    isMoveing = false;
    shutTouch = false;
   } else if (state == state.DOWN) {
    if (getScrollY() <= deltaY) {
     shutTouch = true;
     isMoveing = true;
    }
    deltaY = deltaY < 0 ? 0 : deltaY;
   }
   

代碼很簡單,不過多解釋了,不明確的話,仔細看下源碼確定就明確了。

   

touch 事件處理:

復(fù)制代碼 代碼如下:

/** touch 事件處理 **/
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (inner != null) {
   commOnTouchEvent(ev);
  }
  // ture:禁止控件本身的滑動.
  if (shutTouch)
   return true;
  else
   return super.onTouchEvent(ev);

 }

說明:如果返回值為true,作用:禁止ScrollView的滑動,此時的Touch事件還存哦?。?!如果對Touch事件比擬熟悉的同窗,相信以為我有點空話了,哈哈,我也是個小菜鳥,也卡在這里過。

最后呢,還有個小BUG,也就是那個頂部拉線,如果你讓ScrollView慣性滑動的話,那么你會發(fā)明,頂部線條沒有追隨挪動,其實就是因為慣性滑動的時候我們是獲得不到getScrollY()的值得造成的,查了半天也沒有找到相關(guān)資料,這個問題就臨時就留在這里,有時光了在續(xù)。

這里我將源碼貼出來:

復(fù)制代碼 代碼如下:

package com.example.scrollviewdemo;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.ScrollView;

/**
 * 自定義ScrollView
 *
 * @author jia
 *
 */
public class PersonalScrollView extends ScrollView {

 private final String TAG = PersonalScrollView.class.getSimpleName();

 private View inner;// 孩子View

 private float touchY;// 點擊時Y坐標

 private float deltaY;// Y軸滑動的距離

 private float initTouchY;// 初次點擊的Y坐標

 private boolean shutTouch = false;// 是不是關(guān)閉ScrollView的滑動.

 private Rect normal = new Rect();// 矩形(這里只是個形式,只是用于判斷是不是須要動畫.)

 private boolean isMoveing = false;// 是不是開始挪動.

 private ImageView imageView;// 背景圖控件.
 private View line_up;// 上線
 private int line_up_top;// 上線的top
 private int line_up_bottom;// 上線的bottom

 private int initTop, initBottom;// 初始高度

 private int current_Top, current_Bottom;// 拖動時時高度。

 private int lineUp_current_Top, lineUp_current_Bottom;// 上線

 private onTurnListener turnListener;

 private ImageView imageHeader;

 public void setImageHeader(ImageView imageHeader) {
  this.imageHeader = imageHeader;
 }

 // 狀態(tài):上部,下部,默認
 private enum State {
  UP, DOWN, NOMAL
 };

 // 默認狀態(tài)
 private State state = State.NOMAL;

 public void setTurnListener(onTurnListener turnListener) {
  this.turnListener = turnListener;
 }

 public void setLine_up(View line_up) {
  this.line_up = line_up;
 }

 // 注入背景圖
 public void setImageView(ImageView imageView) {
  this.imageView = imageView;
 }

 /***
  * 構(gòu)造方法
  *
  * @param context
  * @param attrs
  */
 public PersonalScrollView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }

 /***
  * 根據(jù) XML 生成視圖工作實現(xiàn).該函數(shù)在生成視圖的最后調(diào)用,在所有子視圖添加完以后. 即使子類覆蓋了 onFinishInflate
  * 方法,也應(yīng)當調(diào)用父類的方法,使該方法得以執(zhí)行.
  */
 @Override
 protected void onFinishInflate() {
  if (getChildCount() > 0) {
   inner = getChildAt(0);
  }
 }

 /** touch 事件處理 **/
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (inner != null) {
   commOnTouchEvent(ev);
  }
  // ture:禁止控件本身的滑動.
  if (shutTouch)
   return true;
  else
   return super.onTouchEvent(ev);

 }

 /***
  * 觸摸事件
  *
  * @param ev
  */
 public void commOnTouchEvent(MotionEvent ev) {
  int action = ev.getAction();
  switch (action) {
  case MotionEvent.ACTION_DOWN:
   initTouchY = ev.getY();
   current_Top = initTop = imageView.getTop();
   current_Bottom = initBottom = imageView.getBottom();
   if (line_up_top == 0) {
    lineUp_current_Top = line_up_top = line_up.getTop();
    lineUp_current_Bottom = line_up_bottom = line_up.getBottom();
   }
   break;
  case MotionEvent.ACTION_UP:
   /** 回縮動畫 **/
   if (isNeedAnimation()) {
    animation();
   }

   if (getScrollY() == 0) {
    state = State.NOMAL;
   }

   isMoveing = false;
   touchY = 0;
   shutTouch = false;
   break;

  /***
   * 消除出第一次挪動計算,因為第一次無法得知deltaY的高度, 然而我們也要進行初始化,就是第一次挪動的時候讓滑動距離歸0.
   * 以后記載精確了就正常執(zhí)行.
   */
  case MotionEvent.ACTION_MOVE:

   touchY = ev.getY();
   deltaY = touchY - initTouchY;// 滑動距離

   /** 對于初次Touch操作要判斷方位:UP OR DOWN **/
   if (deltaY < 0 && state == state.NOMAL) {
    state = State.UP;
   } else if (deltaY > 0 && state == state.NOMAL) {
    state = State.DOWN;
   }

   if (state == State.UP) {
    deltaY = deltaY < 0 ? deltaY : 0;
    isMoveing = false;
    shutTouch = false;

    /** line_up **/
    lineUp_current_Top = (int) (line_up_top - getScrollY());
    lineUp_current_Bottom = (int) (line_up_bottom - getScrollY());

    Log.e(TAG, "top=" + getScrollY());

    line_up.layout(line_up.getLeft(), lineUp_current_Top,
      line_up.getRight(), lineUp_current_Bottom);

   } else if (state == state.DOWN) {
    if (getScrollY() <= deltaY) {
     shutTouch = true;
     isMoveing = true;
    }
    deltaY = deltaY < 0 ? 0 : deltaY;
   }

   if (isMoveing) {
    // 初始化頭部矩形
    if (normal.isEmpty()) {
     // 保存正常的布局位置
     normal.set(inner.getLeft(), inner.getTop(),
       inner.getRight(), inner.getBottom());
    }
    // 挪動布局(手勢挪動的1/3)
    float inner_move_H = deltaY / 5;

    inner.layout(normal.left, (int) (normal.top + inner_move_H),
      normal.right, (int) (normal.bottom + inner_move_H));

    /** image_bg **/
    float image_move_H = deltaY / 10;
    current_Top = (int) (initTop + image_move_H);
    current_Bottom = (int) (initBottom + image_move_H);
    imageView.layout(imageView.getLeft(), current_Top,
      imageView.getRight(), current_Bottom);

    /** line_up **/
    lineUp_current_Top = (int) (line_up_top + inner_move_H);
    lineUp_current_Bottom = (int) (line_up_bottom + inner_move_H);
    line_up.layout(line_up.getLeft(), lineUp_current_Top,
      line_up.getRight(), lineUp_current_Bottom);
   }
   break;

  default:
   break;

  }
 }

 /***
  * 回縮動畫
  */
 public void animation() {

  TranslateAnimation image_Anim = new TranslateAnimation(0, 0,
    Math.abs(initTop - current_Top), 0);
  image_Anim.setDuration(200);
  imageView.startAnimation(image_Anim);

  imageView.layout(imageView.getLeft(), (int) initTop,
    imageView.getRight(), (int) initBottom);

  // 開啟挪動動畫
  TranslateAnimation inner_Anim = new TranslateAnimation(0, 0,
    inner.getTop(), normal.top);
  inner_Anim.setDuration(200);
  inner.startAnimation(inner_Anim);
  inner.layout(normal.left, normal.top, normal.right, normal.bottom);

  /** line_up **/
  TranslateAnimation line_up_Anim = new TranslateAnimation(0, 0,
    Math.abs(line_up_top - lineUp_current_Top), 0);
  line_up_Anim.setDuration(200);
  line_up.startAnimation(line_up_Anim);
  line_up.layout(line_up.getLeft(), line_up_top, line_up.getRight(),
    line_up_bottom);

  normal.setEmpty();

  /** 動畫執(zhí)行 **/
  if (current_Top > initTop + 50 && turnListener != null)
   turnListener.onTurn();

 }

 /** 是不是須要開啟動畫 **/
 public boolean isNeedAnimation() {
  return !normal.isEmpty();
 }

 /***
  * 執(zhí)行翻轉(zhuǎn)
  *
  * @author jia
  *
  */
 public interface onTurnListener {

  /** 必須到達必定水平才執(zhí)行 **/
  void onTurn();
 }

}

效果圖:

 

    

 界面有點丑陋,不過UI可以自己根據(jù)需求進行調(diào)整.

相關(guān)文章

  • Android入門之日歷選擇與時間選擇組件的使用

    Android入門之日歷選擇與時間選擇組件的使用

    這篇文章主要為大家詳細介紹了Android中TimePicker時間選擇與DatePicker日期選擇組件的使用方法,文中的示例代碼講解詳細,需要的朋友可以參考下
    2022-11-11
  • Android實現(xiàn)過渡動畫、引導(dǎo)頁 Android判斷是否第一次啟動App

    Android實現(xiàn)過渡動畫、引導(dǎo)頁 Android判斷是否第一次啟動App

    這篇文章主要為大家詳細介紹了Android實現(xiàn)過渡動畫、引導(dǎo)頁,以及Android判斷是否第一次啟動App,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android性能優(yōu)化之線程監(jiān)控與線程統(tǒng)一詳解

    Android性能優(yōu)化之線程監(jiān)控與線程統(tǒng)一詳解

    這篇文章主要為大家介紹了Android性能優(yōu)化之線程監(jiān)控與線程統(tǒng)一詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器

    Kotlin圖文并茂講解續(xù)體與續(xù)體攔截器和調(diào)度器

    這篇文章主要介紹了Kotlin開發(fā)中續(xù)體與續(xù)體攔截器和調(diào)度器的相關(guān)使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 詳解Android 華為凹口屏適配小結(jié)

    詳解Android 華為凹口屏適配小結(jié)

    這篇文章主要介紹了Android 華為凹口屏適配小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • Android開發(fā)之ClipboardManager剪貼板功能示例

    Android開發(fā)之ClipboardManager剪貼板功能示例

    這篇文章主要介紹了Android開發(fā)之ClipboardManager剪貼板功能,結(jié)合簡單實例形式分析了Android使用ClipboardManager實現(xiàn)剪貼板功能的相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • 進度條ProgressBar及ProgressDialog(實例)

    進度條ProgressBar及ProgressDialog(實例)

    下面小編就為大家?guī)硪黄M度條ProgressBar及ProgressDialog(實例)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Android 個人理財工具六:顯示賬單明細 下

    Android 個人理財工具六:顯示賬單明細 下

    本文主要節(jié)誒是Android 個人理財工具顯示賬單明細,主要實現(xiàn)此窗口的查詢和刪除功能,這里提供實現(xiàn)代碼,有興趣的小伙伴可以參考下
    2016-08-08
  • Android 照片選擇區(qū)域功能實現(xiàn)示例

    Android 照片選擇區(qū)域功能實現(xiàn)示例

    這篇文章主要介紹了Android 照片選擇區(qū)域功能實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Android仿微信QQ設(shè)置圖形頭像裁剪功能

    Android仿微信QQ設(shè)置圖形頭像裁剪功能

    最近在做畢業(yè)設(shè)計,想有一個功能和QQ一樣可以裁剪頭像并設(shè)置圓形頭像.圖片裁剪實現(xiàn)方式有兩種,一種是利用系統(tǒng)自帶的裁剪工具,一種是使用開源工具Cropper。本節(jié)就為大家?guī)砣绾问褂孟到y(tǒng)自帶的裁剪工具進行圖片裁剪
    2016-10-10

最新評論