Android實(shí)現(xiàn)ImageView圖片雙擊放大及縮小

public classDoubleScaleImageViewextendsAppCompatImageViewimplementsView.OnTouchListener,ViewTreeObserver.OnGlobalLayoutListener{

? ? private boolean isFirst = false;

? ? private float doubleScale;// 雙擊放大的值? ? private Matrix mScaleMatrix;

? ? private float defaultScale;// 默認(rèn)的縮放值? ? private int mLastPinterCount;// 記錄上一次多點(diǎn)觸控的數(shù)量? ? private float mLastX;

? ? private float mLastY;

? ? private int mTouchSlop;

? ? private boolean isCanDrag;

? ? private boolean isCheckLeft;

? ? private boolean isCheckTop;

? ? private GestureDetector mGestureDetector;

? ? publicDoubleScaleImageView(Context context){

? ? ? ? this(context, null);

? ? }

? ? publicDoubleScaleImageView(Context context, AttributeSet attrs){

? ? ? ? this(context, attrs, 0);

? ? }

? ? publicDoubleScaleImageView(Context context, AttributeSet attrs,intdefStyleAttr){

? ? ? ? super(context, attrs, defStyleAttr);

? ? ? ? mScaleMatrix = new Matrix();

? ? ? ? setScaleType(ScaleType.MATRIX);

? ? ? ? setOnTouchListener(this);

? ? ? ? // getScaledTouchSlop是一個(gè)距離只祠,表示滑動(dòng)的時(shí)候裸影,手的移動(dòng)要大于這個(gè)距離才開始移動(dòng)控件萍桌。如果小于這個(gè)距離就不觸發(fā)移動(dòng)控件? ? ? ? mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

? ? ? ? mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {

? ? ? ? ? ? @Override? ? ? ? ? ? publicbooleanonDoubleTap(MotionEvent e){

? ? ? ? ? ? ? ? float x = e.getX();

? ? ? ? ? ? ? ? float y = e.getY();

? ? ? ? ? ? ? ? if (getScale() < doubleScale) {

? ? ? ? ? ? ? ? ? ? mScaleMatrix.postScale(doubleScale / getScale(), doubleScale / getScale(), x, y);// 放大? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else {

? ? ? ? ? ? ? ? ? ? mScaleMatrix.postScale(defaultScale / getScale(), defaultScale / getScale(), x, y);// 縮小? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? setImageMatrix(mScaleMatrix);

? ? ? ? ? ? ? ? return super.onDoubleTap(e);

? ? ? ? ? ? }

? ? ? ? });

? ? }

? ? @Override? ? protectedvoidonAttachedToWindow(){// view附加到窗體上時(shí)調(diào)用該方法? ? ? ? super.onAttachedToWindow();

? ? ? ? getViewTreeObserver().addOnGlobalLayoutListener(this);

? ? }

? ? @SuppressWarnings("deprecation")

? ? @Override? ? protectedvoidonDetachedFromWindow(){// 將視圖從窗體上分離的時(shí)候調(diào)用該方法。? ? ? ? super.onDetachedFromWindow();

? ? ? ? getViewTreeObserver().removeGlobalOnLayoutListener(this);

? ? }

? ? @Override? ? publicvoidonGlobalLayout(){// 在這個(gè)方法中獲取ImageView加載完成后的圖片? ? ? ? if (!isFirst) {

? ? ? ? ? ? // 獲取控件的寬度和高度? ? ? ? ? ? int width = getWidth();

? ? ? ? ? ? int height = getHeight();

? ? ? ? ? ? // 得到我們的圖片以及圖片的寬度及高度? ? ? ? ? ? Drawable drawable = getDrawable();

? ? ? ? ? ? if (drawable == null) { return; }

? ? ? ? ? ? int imageWidth = drawable.getIntrinsicWidth();// 圖片的寬度? ? ? ? ? ? int imageHeight = drawable.getIntrinsicHeight();// 圖片的高度? ? ? ? ? ? float scale = 1.0f;

? ? ? ? ? ? // 如果圖片寬度大于控件寬度度硝,但是圖片高度小于控件 高度肿轨,我們要縮小圖片? ? ? ? ? ? if (imageWidth > width && imageHeight < height) {

? ? ? ? ? ? ? ? scale = width * 1.0f / imageWidth;

? ? ? ? ? ? }

? ? ? ? ? ? // 如果圖片寬度小于控件寬度,但是圖片高度大于控件 高度塘淑,我們要縮小圖片? ? ? ? ? ? if (imageWidth < width && imageHeight > height) {

? ? ? ? ? ? ? ? scale = height * 1.0f / imageHeight;

? ? ? ? ? ? }

? ? ? ? ? ? // 如果圖片的寬度都 大于或小于控件寬度萝招,我們則要對(duì)圖片進(jìn)行對(duì)應(yīng)縮放,保證圖片占滿控件? ? ? ? ? ? if ((imageWidth > width && imageHeight > height) || (imageWidth < width && imageHeight < height)) {

? ? ? ? ? ? ? ? scale = Math.min(width * 1.0f / imageWidth, height * 1.0f / imageHeight);

? ? ? ? ? ? }

? ? ? ? ? ? // 初始化對(duì)應(yīng)的縮放值? ? ? ? ? ? defaultScale = scale;

? ? ? ? ? ? doubleScale = defaultScale * 2;

? ? ? ? ? ? // 圖片縮放后存捺,將圖片要移動(dòng)到控件中心? ? ? ? ? ? int dx = width / 2 - imageWidth / 2;

? ? ? ? ? ? int dy = height / 2 - imageHeight / 2;

? ? ? ? ? ? mScaleMatrix.postTranslate(dx, dy);

? ? ? ? ? ? mScaleMatrix.postScale(defaultScale, defaultScale, width / 2, height / 2);

? ? ? ? ? ? setImageMatrix(mScaleMatrix);

? ? ? ? ? ? isFirst = true;

? ? ? ? }

? ? }

? ? @Override? ? publicbooleanonTouch(View v, MotionEvent event){

? ? ? ? if (mGestureDetector.onTouchEvent(event)) { return true; }

? ? ? ? float x = 0;

? ? ? ? float y = 0;

? ? ? ? int pointerCount = event.getPointerCount();// 獲取放在屏幕上的手指數(shù)量? ? ? ? for (int i = 0; i < pointerCount; i++) {

? ? ? ? ? ? x += event.getX(i);

? ? ? ? ? ? y += event.getY(i);

? ? ? ? }

? ? ? ? x /= pointerCount;

? ? ? ? y /= pointerCount;

? ? ? ? if (mLastPinterCount != pointerCount) {

? ? ? ? ? ? isCanDrag = false;

? ? ? ? ? ? mLastX = x;

? ? ? ? ? ? mLastY = y;

? ? ? ? }

? ? ? ? mLastPinterCount = pointerCount;

? ? ? ? switch (event.getAction()) {

? ? ? ? ? ? case MotionEvent.ACTION_MOVE:

? ? ? ? ? ? ? ? float dx = x - mLastX;

? ? ? ? ? ? ? ? float dy = y - mLastY;

? ? ? ? ? ? ? ? isCanDrag = isMove(dx, dy);

? ? ? ? ? ? ? ? if (isCanDrag) {

? ? ? ? ? ? ? ? ? ? RectF rectf = getMatrixRectf();

? ? ? ? ? ? ? ? ? ? if (null != getDrawable()) {

? ? ? ? ? ? ? ? ? ? ? ? isCheckLeft = isCheckTop = true;

? ? ? ? ? ? ? ? ? ? ? ? if (rectf.width() < getWidth()) {// 如果圖片寬度小于控件寬度(屏幕寬度)不允許橫向移動(dòng)? ? ? ? ? ? ? ? ? ? ? ? ? ? dx = 0;

? ? ? ? ? ? ? ? ? ? ? ? ? ? isCheckLeft = false;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? if (rectf.height() < getHeight()) {// 如果圖片高度小于控件高度(屏幕高度)不允許縱向移動(dòng)? ? ? ? ? ? ? ? ? ? ? ? ? ? dy = 0;

? ? ? ? ? ? ? ? ? ? ? ? ? ? isCheckTop = false;

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? mScaleMatrix.postTranslate(dx, dy);

? ? ? ? ? ? ? ? ? ? ? ? checkTranslateWithBorder();

? ? ? ? ? ? ? ? ? ? ? ? setImageMatrix(mScaleMatrix);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? mLastX = x;

? ? ? ? ? ? ? ? mLastY = y;

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case MotionEvent.ACTION_UP:

? ? ? ? ? ? case MotionEvent.ACTION_CANCEL:

? ? ? ? ? ? ? ? mLastPinterCount = 0;

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? return true;

? ? }

? ? /**

? ? * 移動(dòng)圖片時(shí)進(jìn)行邊界檢查

? ? */? ? privatevoidcheckTranslateWithBorder(){

? ? ? ? RectF rectf = getMatrixRectf();

? ? ? ? float delX = 0;

? ? ? ? float delY = 0;

? ? ? ? int width = getWidth();

? ? ? ? int height = getHeight();

? ? ? ? if (rectf.top > 0 && isCheckTop) {

? ? ? ? ? ? delY = -rectf.top;

? ? ? ? }

? ? ? ? if (rectf.bottom < height && isCheckTop) {

? ? ? ? ? ? delY = height - rectf.bottom;

? ? ? ? }

? ? ? ? if (rectf.left > 0 && isCheckLeft) {

? ? ? ? ? ? delX = -rectf.left;

? ? ? ? }

? ? ? ? if (rectf.right < width && isCheckLeft) {

? ? ? ? ? ? delX = width - rectf.right;

? ? ? ? }

? ? ? ? mScaleMatrix.postTranslate(delX, delY);

? ? }

? ? // 判斷是否有移動(dòng)? ? privatebooleanisMove(floatx,floaty){

? ? ? ? return Math.sqrt(x * x + y * y) > mTouchSlop;

? ? }

? ? /**

? ? * 獲取圖片的位置

? ? */? ? privateRectFgetMatrixRectf(){

? ? ? ? Matrix matrix = mScaleMatrix;

? ? ? ? RectF recft = new RectF();

? ? ? ? if (getDrawable() != null) {

? ? ? ? ? ? recft.set(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());

? ? ? ? ? ? matrix.mapRect(recft);

? ? ? ? }

? ? ? ? return recft;

? ? }

? ? // 獲取當(dāng)前圖片的縮放值? ? privatefloatgetScale(){

? ? ? ? float values[] = new float[9];

? ? ? ? mScaleMatrix.getValues(values);

? ? ? ? return values[Matrix.MSCALE_X];

? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末槐沼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子捌治,更是在濱河造成了極大的恐慌岗钩,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肖油,死亡現(xiàn)場離奇詭異兼吓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)森枪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門视搏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人县袱,你說我怎么就攤上這事浑娜。” “怎么了式散?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵筋遭,是天一觀的道長。 經(jīng)常有香客問我暴拄,道長漓滔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任乖篷,我火速辦了婚禮响驴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撕蔼。我一直安慰自己踏施,他們只是感情好石蔗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布罕邀。 她就那樣靜靜地躺著畅形,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诉探。 梳的紋絲不亂的頭發(fā)上日熬,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音肾胯,去河邊找鬼竖席。 笑死,一個(gè)胖子當(dāng)著我的面吹牛敬肚,可吹牛的內(nèi)容都是我干的毕荐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼艳馒,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼憎亚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起弄慰,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤第美,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后陆爽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體什往,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年慌闭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了别威。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驴剔,死狀恐怖省古,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仔拟,我是刑警寧澤衫樊,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站利花,受9級(jí)特大地震影響科侈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炒事,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一臀栈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挠乳,春花似錦权薯、人聲如沸姑躲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黍析。三九已至,卻和暖如春屎开,著一層夾襖步出監(jiān)牢的瞬間阐枣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工奄抽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔼两,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓逞度,卻偏偏與公主長得像额划,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子档泽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容