一、概述现在app中,图片预览功能肯定是少不了的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始移动到指定部位~~~

我相信看图的整个步骤,大家或者说用户应该不希望被打断把~~~“我擦,竟然不能放大,什么玩意,卸了~~“ , "我擦,竟然不能移动,留有何用,卸了~~"。

哈~所以对于图片的预览,一来,我们要让用户爽;二来,我们作为开发者,也得知道如何实现~~~

想要做到图片支持多点触控,自由的进行缩放、平移,需要了解几个知识点:Matrix , GestureDetector , ScaleGestureDetector 以及事件分发机制,ps:不会咋办,不会你懂的。

二、Matrix矩阵,看深入了都是3维矩阵的乘啊什么的,怪麻烦的~~

其实这么了解下就行了:

Matrix

数据结构:3维矩阵;

内部存储:new Float[9] ; 内部就是个一维数组,内部9个元素;可以进行setValues(float[] values)进行初始化

每个元素代表的意思:

{

MSCALE_X, MSKEW_X, MTRANS_X,

MSKEW_Y, MSCALE_Y, MTRANS_Y,

MPERSP_0, MPERSP_1, MPERSP_2

};

字面上,应该能看出来哪个代表x方向缩放,哪个代表垂直方向的偏移量吧~~有不认识的3个,没事,请无视。

操作

比如你想要设置matrix的偏移量为200,100

你可以这么写:

Matrix transMatrix = new Matrix();

float[] values = new float[] { 1.0, 0, 200, 0, 1.0, 100, 0, 0, 1.0 };

transMatrix.setValues(values);

如果需要在旋转30度,放大两倍~~

这么写其实怪麻烦的~~

Matrix提供了一些常用的API:例如我们可以这么写:

Matrix transMatrix = new Matrix();

transMatrix.postTranslate(200, 100);

如何获取值:

当然了,我们对一个Matrix进行了各种操作,一会postScale,一会postTranslate;那么现在如何获得当前的缩放比例:

前面说setValues可以初始化,那么getValues就能拿到当前矩阵的值,拿到的是个一维数组,9个元素;再通过下标取对应值就可以。

比如我想知道现在x方向缩放比例:

public final float getScale()

{

scaleMatrix.getValues(matrixValues);

return matrixValues[Matrix.MSCALE_X];

}

好了,知道这些就够了~~

GestureDetector :

嗯,自己看API,能够捕捉到长按、双击什么的;用法会在例子中

ScaleGestureDetector:

嗯,有点像继承来的,其实不是的,独立的一个类~用于检测缩放的手势~~~用法会在例子中

三、实战为了大家更好的理解,我会独立出每个功能,最后再整合到一起~~也方面大家对每个API的使用的学习。

1、自由的缩放

需求:当图片加载时,将图片在屏幕中居中;图片宽或高大于屏幕的,缩小至屏幕大小;自由对图片进行方法或缩小;

代码不是很长,直接贴代码了:

package com.zhy.view;

import android.content.Context;

import android.graphics.Matrix;

import android.graphics.drawable.Drawable;

import android.util.AttributeSet;

import android.util.Log;

import android.view.MotionEvent;

import android.view.ScaleGestureDetector;

import android.view.ScaleGestureDetector.OnScaleGestureListener;

import android.view.View;

import android.view.View.OnTouchListener;

import android.view.ViewTreeObserver;

import android.widget.ImageView;

public class ZoomImageView extends ImageView implements OnScaleGestureListener,

OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener

{

private static final String TAG = ZoomImageView.class.getSimpleName();

public static final float SCALE_MAX = 4.0f;

/**

* 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0

*/

private float initScale = 1.0f;

/**

* 用于存放矩阵的9个值

*/

private final float[] matrixValues = new float[9];

private boolean once = true;

/**

* 缩放的手势检测

*/

private ScaleGestureDetector mScaleGestureDetector = null;

private final Matrix mScaleMatrix = new Matrix();

public ZoomImageView(Context context)

{

this(context, null);

}

public ZoomImageView(Context context, AttributeSet attrs)

{

super(context, attrs);

super.setScaleType(ScaleType.MATRIX);

mScaleGestureDetector = new ScaleGestureDetector(context, this);

this.setOnTouchListener(this);

}

@Override

public boolean onScale(ScaleGestureDetector detector)

{

float scale = getScale();

float scaleFactor = detector.getScaleFactor();

if (getDrawable() == null)

return true;

/**

* 缩放的范围控制

*/

if ((scale < SCALE_MAX && scaleFactor > 1.0f)

|| (scale > initScale && scaleFactor < 1.0f))

{

/**

* 最大值最小值判断

*/

if (scaleFactor * scale < initScale)

{

scaleFactor = initScale / scale;

}

if (scaleFactor * scale > SCALE_MAX)

{

scaleFactor = SCALE_MAX / scale;

}

/**

* 设置缩放比例

*/

mScaleMatrix.postScale(scaleFactor, scaleFactor, getWidth() / 2,

getHeight() / 2);

setImageMatrix(mScaleMatrix);

}

return true;

}

@Override

public boolean onScaleBegin(ScaleGestureDetector detector)

{

return true;

}

@Override

public void onScaleEnd(ScaleGestureDetector detector)

{

}

@Override

public boolean onTouch(View v, MotionEvent event)

{

return mScaleGestureDetector.onTouchEvent(event);

}

/**

* 获得当前的缩放比例

*

* @return

*/

public final float getScale()

{

mScaleMatrix.getValues(matrixValues);

return matrixValues[Matrix.MSCALE_X];

}

@Override

protected void onAttachedToWindow()

{

super.onAttachedToWindow();

getViewTreeObserver().addOnGlobalLayoutListener(this);

}

@SuppressWarnings("deprecation")

@Override

protected void onDetachedFromWindow()

{

super.onDetachedFromWindow();

getViewTreeObserver().removeGlobalOnLayoutListener(this);

}

@Override

public void onGlobalLayout()

{

if (once)

{

Drawable d = getDrawable();

if (d == null)

return;

Log.e(TAG, d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());

int width = getWidth();

int height = getHeight();

// 拿到图片的宽和高

int dw = d.getIntrinsicWidth();

int dh = d.getIntrinsicHeight();

float scale = 1.0f;

// 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高

if (dw > width && dh <= height)

{

scale = width * 1.0f / dw;

}

if (dh > height && dw <= width)

{

scale = height * 1.0f / dh;

}

// 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小

if (dw > width && dh > height)

{

scale = Math.min(dw * 1.0f / width, dh * 1.0f / height);

}

initScale = scale;

// 图片移动至屏幕中心

mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);

mScaleMatrix

.postScale(scale, scale, getWidth() / 2, getHeight() / 2);

setImageMatrix(mScaleMatrix);

once = false;

}

}

}

我们在onGlobalLayout的回调中,根据图片的宽和高以及屏幕的宽和高,对图片进行缩放以及移动至屏幕的中心。如果图片很小,那就正常显示,不放大了~

我们让OnTouchListener的MotionEvent交给ScaleGestureDetector进行处理

@Override

public boolean onTouch(View v, MotionEvent event)

{

return mScaleGestureDetector.onTouchEvent(event);

}

2、在onScale的回调中对图片进行缩放的控制,首先进行缩放范围的判断,然后设置mScaleMatrix的scale值

现在的效果:

小于屏幕的宽和高

大于屏幕的宽和高

真机录的效果不太好~~凑合看~

现在已经能够~~~随意的放大缩小了~~~

可是,可是,存在问题:

(1)缩放的中心点,我们设置是固定的,屏幕中间

(2)放大后,无法移动~

下面,我们先解决缩放的中心点问题,不能一直按屏幕中心么,像我这样的,我比较关注妹子的眼睛,我要放大那一块~~~

(1)设置缩放中心

(2)单纯的设置缩放中心

仅仅是设置中心很简单,直接修改下中心点 :

/**

* 设置缩放比例

*/

mScaleMatrix.postScale(scaleFactor, scaleFactor,

detector.getFocusX(), detector.getFocusX());

setImageMatrix(mScaleMatrix);

但是,随意的中心点放大、缩小,会导致图片的位置的变化,最终导致,图片宽高大于屏幕时,图片与屏幕间出现白边;图片小于屏幕,但是不居中。

3、控制缩放时图片显示的范围

所以我们在缩放的时候需要手动控制下范围:

/**

* 在缩放时,进行图片显示范围的控制

*/

private void checkBorderAndCenterWhenScale()

{

RectF rect = getMatrixRectF();

float deltaX = 0;

float deltaY = 0;

int width = getWidth();

int height = getHeight();

// 如果宽或高大于屏幕,则控制范围

if (rect.width() >= width)

{

if (rect.left > 0)

{

deltaX = -rect.left;

}

if (rect.right < width)

{

deltaX = width - rect.right;

}

}

if (rect.height() >= height)

{

if (rect.top > 0)

{

deltaY = -rect.top;

}

if (rect.bottom < height)

{

deltaY = height - rect.bottom;

}

}

// 如果宽或高小于屏幕,则让其居中

if (rect.width() < width)

{

deltaX = width * 0.5f - rect.right + 0.5f * rect.width();

}

if (rect.height() < height)

{

deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();

}

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

mScaleMatrix.postTranslate(deltaX, deltaY);

}

/**

* 根据当前图片的Matrix获得图片的范围

*

* @return

*/

private RectF getMatrixRectF()

{

Matrix matrix = mScaleMatrix;

RectF rect = new RectF();

Drawable d = getDrawable();

if (null != d)

{

rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());

matrix.mapRect(rect);

}

return rect;

}

在onScale里面记得调用:

/**

* 设置缩放比例

*/

mScaleMatrix.postScale(scaleFactor, scaleFactor,

detector.getFocusX(), detector.getFocusY());

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

这样就好了,可以自由的放大任何地方,并且不会出现边界出现白边,也能很好的让图片显示在屏幕中间(当图片宽或高小于屏幕);

贴下布局文件:

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:scaleType="matrix"

android:src="@drawable/xx" />

眼睛是心灵的窗户,咱们来放大看看,效果图:

四、进阶

1、自由的进行移动下面继续完善我们的ImageView~~

首先加入放大后的移动~~

我们在onTouchEvent里面,加上移动的代码,当然了,必须长或宽大于屏幕才可以移动~~~

@Override

public boolean onTouch(View v, MotionEvent event)

{

mScaleGestureDetector.onTouchEvent(event);

float x = 0, y = 0;

// 拿到触摸点的个数

final int pointerCount = event.getPointerCount();

// 得到多个触摸点的x与y均值

for (int i = 0; i < pointerCount; i++)

{

x += event.getX(i);

y += event.getY(i);

}

x = x / pointerCount;

y = y / pointerCount;

/**

* 每当触摸点发生变化时,重置mLasX , mLastY

*/

if (pointerCount != lastPointerCount)

{

isCanDrag = false;

mLastX = x;

mLastY = y;

}

lastPointerCount = pointerCount;

switch (event.getAction())

{

case MotionEvent.ACTION_MOVE:

Log.e(TAG, "ACTION_MOVE");

float dx = x - mLastX;

float dy = y - mLastY;

if (!isCanDrag)

{

isCanDrag = isCanDrag(dx, dy);

}

if (isCanDrag)

{

RectF rectF = getMatrixRectF();

if (getDrawable() != null)

{

isCheckLeftAndRight = isCheckTopAndBottom = true;

// 如果宽度小于屏幕宽度,则禁止左右移动

if (rectF.width() < getWidth())

{

dx = 0;

isCheckLeftAndRight = false;

}

// 如果高度小雨屏幕高度,则禁止上下移动

if (rectF.height() < getHeight())

{

dy = 0;

isCheckTopAndBottom = false;

}

mScaleMatrix.postTranslate(dx, dy);

checkMatrixBounds();

setImageMatrix(mScaleMatrix);

}

}

mLastX = x;

mLastY = y;

break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_CANCEL:

Log.e(TAG, "ACTION_UP");

lastPointerCount = 0;

break;

}

return true;

}

首先我们拿到触摸点的数量,然后求出多个触摸点的平均值,设置给我们的mLastX , mLastY , 然后在移动的时候,得到dx ,dy 进行范围检查以后,调用mScaleMatrix.postTranslate进行设置偏移量,当然了,设置完成以后,还需要再次校验一下,不能把图片移动的与屏幕边界出现白边,校验完成后,调用setImageMatrix.

这里:需要注意一下,我们没有复写ACTION_DOWM,是因为,ACTION_DOWN在多点触控的情况下,只要有一个手指按下状态,其他手指按下不会再次触发ACTION_DOWN,但是多个手指以后,触摸点的平均值会发生很大变化,所以我们没有用到ACTION_DOWN。每当触摸点的数量变化,我们就会跟新当前的mLastX,mLastY.

下面是上面用到的两个私有方法,一个用于检查边界,一个用于判断是否是拖动的操作:

/**

* 移动时,进行边界判断,主要判断宽或高大于屏幕的

*/

private void checkMatrixBounds()

{

RectF rect = getMatrixRectF();

float deltaX = 0, deltaY = 0;

final float viewWidth = getWidth();

final float viewHeight = getHeight();

// 判断移动或缩放后,图片显示是否超出屏幕边界

if (rect.top > 0 && isCheckTopAndBottom)

{

deltaY = -rect.top;

}

if (rect.bottom < viewHeight && isCheckTopAndBottom)

{

deltaY = viewHeight - rect.bottom;

}

if (rect.left > 0 && isCheckLeftAndRight)

{

deltaX = -rect.left;

}

if (rect.right < viewWidth && isCheckLeftAndRight)

{

deltaX = viewWidth - rect.right;

}

mScaleMatrix.postTranslate(deltaX, deltaY);

}

/**

* 是否是推动行为

*

* @param dx

* @param dy

* @return

*/

private boolean isCanDrag(float dx, float dy)

{

return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;

}

这样,我们就可以快乐的放大、缩小加移动了~~~

效果图:这次换个男人的图片,我们越狱的主角之一,TBug~

我们的缩放+移动搞定~~

2、双击放大与缩小谈到双击事件,我们的GestureDetector终于要登场了,这哥们可以捕获双击事件~~

(1)GestureDetector的使用

因为GestureDetector设置监听器的话,方法一大串,而我们只需要onDoubleTap这个回调,所以我们准备使用它的一个内部类SimpleOnGestureListener,对接口的其他方法实现了空实现。

不过还有几个问题需要讨论下,才能开始我们的代码:

(1)我们双击尺寸如何变化?

我是这样的,根据当前的缩放值,如果是小于2的,我们双击直接到变为原图的2倍;如果是2,4之间的,我们双击直接为原图的4倍;其他状态也就是4倍,双击后还原到最初的尺寸。

如果你觉得这样不合适,可以根据自己的爱好调整。

我们双击变化,需要一个动画~~比如我们上例的演示图,图片很大,全屏显示的时候initScale=0.5左后,如果双击后变为2,也就是瞬间大了四倍,没有一个过渡的效果的话,给用户的感觉会特别差。所以,我们准备使用postDelay执行一个Runnable,Runnable中再次根据的当然的缩放值继续执行。

首先我们在构造方法中,完成对GestureDetector的初始化,以及设置onDoubleTap监听

public ZoomImageView(Context context, AttributeSet attrs)

{

super(context, attrs);

mScaleGestureDetector = new ScaleGestureDetector(context, this);

mGestureDetector = new GestureDetector(context,

new SimpleOnGestureListener()

{

@Override

public boolean onDoubleTap(MotionEvent e)

{

if (isAutoScale == true)

return true;

float x = e.getX();

float y = e.getY();

Log.e("DoubleTap", getScale() + " , " + initScale);

if (getScale() < SCALE_MID)

{

ZoomImageView.this.postDelayed(

new AutoScaleRunnable(SCALE_MID, x, y), 16);

isAutoScale = true;

} else if (getScale() >= SCALE_MID

&& getScale() < SCALE_MAX)

{

ZoomImageView.this.postDelayed(

new AutoScaleRunnable(SCALE_MAX, x, y), 16);

isAutoScale = true;

} else

{

ZoomImageView.this.postDelayed(

new AutoScaleRunnable(initScale, x, y), 16);

isAutoScale = true;

}

return true;

}

});

mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

super.setScaleType(ScaleType.MATRIX);

this.setOnTouchListener(this);

}

当双击的时候,首先判断是否正在自动缩放,如果在,直接retrun ;

然后就进入了我们的if,如果当然是scale小于2,则通过view.发送一个Runnable进行执行;其他类似;

/**

* 自动缩放的任务

*

* @author zhy

*

*/

private class AutoScaleRunnable implements Runnable

{

static final float BIGGER = 1.07f;

static final float SMALLER = 0.93f;

private float mTargetScale;

private float tmpScale;

/**

* 缩放的中心

*/

private float x;

private float y;

/**

* 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小

*

* @param targetScale

*/

public AutoScaleRunnable(float targetScale, float x, float y)

{

this.mTargetScale = targetScale;

this.x = x;

this.y = y;

if (getScale() < mTargetScale)

{

tmpScale = BIGGER;

} else

{

tmpScale = SMALLER;

}

}

@Override

public void run()

{

// 进行缩放

mScaleMatrix.postScale(tmpScale, tmpScale, x, y);

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

final float currentScale = getScale();

//如果值在合法范围内,继续缩放

if (((tmpScale > 1f) && (currentScale < mTargetScale))

|| ((tmpScale < 1f) && (mTargetScale < currentScale)))

{

ZoomImageView.this.postDelayed(this, 16);

} else//设置为目标的缩放比例

{

final float deltaScale = mTargetScale / currentScale;

mScaleMatrix.postScale(deltaScale, deltaScale, x, y);

checkBorderAndCenterWhenScale();

setImageMatrix(mScaleMatrix);

isAutoScale = false;

}

}

}

代码写完了,我们依然需要把我们的event传给它,依然是在onTouch方法:

@Override

public boolean onTouch(View v, MotionEvent event)

{

if (mGestureDetector.onTouchEvent(event))

return true;

好了,双击放大与缩小的功能就搞定了,下面测试下~~~

效果图,终于可以用模拟器了~~

3、处理与ViewPager的冲突直接把我们的图片作为ViewPager的Item,可想而知,肯定有冲突~~

(1)布局文件

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/id_viewpager"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

(2)Activity代码

package com.zhy.zhy_scalegesturedetector02;

import android.app.Activity;

import android.os.Bundle;

import android.support.v4.view.PagerAdapter;

import android.support.v4.view.ViewPager;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import com.zhy.view.ZoomImageView;

public class MainActivity extends Activity

{

private ViewPager mViewPager;

private int[] mImgs = new int[] { R.drawable.tbug, R.drawable.a,

R.drawable.xx };

private ImageView[] mImageViews = new ImageView[mImgs.length];

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.vp);

mViewPager = (ViewPager) findViewById(R.id.id_viewpager);

mViewPager.setAdapter(new PagerAdapter()

{

@Override

public Object instantiateItem(ViewGroup container, int position)

{

ZoomImageView imageView = new ZoomImageView(

getApplicationContext());

imageView.setImageResource(mImgs[position]);

container.addView(imageView);

mImageViews[position] = imageView;

return imageView;

}

@Override

public void destroyItem(ViewGroup container, int position,

Object object)

{

container.removeView(mImageViews[position]);

}

@Override

public boolean isViewFromObject(View arg0, Object arg1)

{

return arg0 == arg1;

}

@Override

public int getCount()

{

return mImgs.length;

}

});

}

}

现在直接运行,发现ViewPager好着呢,但是我们的图片放大以后,移动和ViewPager冲突了,又不能移动了~。。。擦擦擦。。。

(3)处理冲突

现在我们迅速的想一想,记得之前学习过事件分发机制,我们的ZoomImageView在ViewPager中,如果我们不想被拦截,那么如何做呢?

首先不想被拦截的条件是:我们的宽或高大于屏幕宽或高时,因为此时可以移动,我们不想被拦截。接下来,不想被拦截:

getParent().requestDisallowInterceptTouchEvent(true);

一行代码足以,如果你对事件分发中,不被拦截不清晰,可以参考:如何不被拦截 。

放在一起我们的代码就是:

switch (event.getAction())

{

case MotionEvent.ACTION_DOWN:

if (rectF.width() > getWidth() || rectF.height() > getHeight())

{

getParent().requestDisallowInterceptTouchEvent(true);

}

break;

case MotionEvent.ACTION_MOVE:

if (rectF.width() > getWidth() || rectF.height() > getHeight())

{

getParent().requestDisallowInterceptTouchEvent(true);

}

~当宽或高大于屏幕宽或高时,拖动效果认为是移动图片,反之则让ViewPager去处理

此时的效果:

ok,现在已经解决了和ViewPager的冲突,ps:尼玛不应该双击还能放大两次到4倍,,,,,好恶心。。。

(4)到达边界事件交给ViewPager处理

可能有些用户还希望,当图片到达边界时,不能再拖动的时候,能够把事件给ViewPager

那就在ACTION_MOVE中,判断当前已经到达边界,且还在拉的时候,事件交给ViewPager

if (isCanDrag)

{

if (getDrawable() != null)

{

if (getMatrixRectF().left == 0 && dx > 0)

{

getParent().requestDisallowInterceptTouchEvent(false);

}

if (getMatrixRectF().right == getWidth() && dx < 0)

{

getParent().requestDisallowInterceptTouchEvent(false);

}

此时的效果:

好了,其实添加了这个之后,体验一般哈~~~

终于写完了,代码中可能存在BUG,发现问题,或者解决了发现的BUG时,希望可以直接在博客下面留言,也能够方便他人~~

到此,我们的Android 手势检测实战 打造支持缩放平移的图片预览效果 结束~~!

建议把双击放大到4倍的地方,注释掉一个If

// else if (getScale() >= SCALE_MID

// && getScale() < SCALE_MAX)

// {

// ZoomImageView.this.postDelayed(

// new AutoScaleRunnable(SCALE_MAX, x, y), 16);

// isAutoScale = true;

// }

连续双击放大,感觉不爽,代码已经上传,我就不重传了,如果你也觉得不爽,可以自行注释。

android 手势放缩_Android应用中实现手势控制图片缩放的完全攻略相关推荐

  1. VM:如何向vmware虚拟机中传输文件(或者共享文件夹)之详细攻略(图文教程)

    VM:如何向vmware虚拟机中传输文件(或者共享文件夹)之详细攻略(图文教程) 目录 如何向vmware虚拟机中传输文件 1.外部点击安装VMware Tools 2.内部客户机进行安装 3.共享文 ...

  2. 企业上云要几步?中拓互联奉送企业上云全攻略

    企业上云要几步?中拓互联奉送企业上云全攻略 不论是国家倡导的"上云用数赋智",还是由疫情引发的强烈需求,这两年成长型企业上云,可谓是如火如荼. 图片来源于:人民政府网 虚无缥缈的一 ...

  3. Dataset:机器学习中常用数据集下载链接集合之详细攻略

    Dataset:机器学习中常用数据集下载链接集合之详细攻略 目录 机器学习中常用数据集下载链接集合之详细攻略 sklearn.datasets数据集所有csv文件集合 seaborn-data数据集所 ...

  4. CREO:CREO软件之工程图界面的简介(【创建】、【布局】、【表】、【注释】、【插入页面】、【装配图出工程图】、【将视图转为绘制图元】、【工程图输入到CAD中去修改】)图文教程之详细攻略

    CREO:CREO软件之工程图界面的简介([创建].[布局].[表].[注释].[插入页面].[装配图出工程图].[将视图转为绘制图元].[工程图输入到CAD中去修改])图文教程之详细攻略 目录 CR ...

  5. android 手势放缩_Android 手势识别—缩放

    上一篇讲解了手势识别中的点击和双击事件的识别,用到的是GestureDetector类和GestureDetectorCompat类,用于监听用户触摸屏幕中的简单动作. 缩放 基本用法如下,可以通过缩 ...

  6. android matrix 实现点击旋转,Android中利用matrix 控制图片的旋转、缩放、移动

    本文主要讲解利用android中Matrix控制图形的旋转缩放移动,具体参见一下代码: /** * 使用矩阵控制图片移动.缩放.旋转 */ public class CommonImgEffectVi ...

  7. TF之data_format:data_format中的NHWCNCHW简介、转换的详细攻略

    TF之data_format:data_format中的NHWC&NCHW简介.转换的详细攻略 目录 NHWC&NCHW简介 NHWC&NCHW转换 NHWC&NCHW ...

  8. mysql中phpmyadmin安装教程_phpMyAdmin 安装教程全攻略

    管理MYSQL数据库的最好工具是PHPmyAdmin,现在最新版本是phpMyAdmin 2.9.0.2,这是一个国际上开源的软件,一直在更新版本,你可以从 http://www.phpmyadmin ...

  9. Android吃鸡 3dtouch,绝地求生刺激战场3Dtouch怎么用 3Dtouch设置攻略

    相信很多小伙伴都已经看到刺激战场最近爆料了很多内容,其中就包含了苹果手机知名的操作技术,那么绝地求生刺激战场3Dtouch怎么用呢,来随小编看看吧. 绝地求生刺激战场3Dtouch怎么设置: Q:绝地 ...

最新文章

  1. idea网页预览功能_IDEA 2020.2 重磅发布,动画级新功能预览!
  2. 929-独特的电子邮件地址
  3. 学习Java编程到底是为了什么,该具备什么样的能力
  4. 如何用shell脚本编译java工程
  5. JAVA synchronized关键字锁机制(中)
  6. [华清远见]FPGA公益培训
  7. React学习途径和资料分享
  8. BZOJ 2957 楼房重建-线段树
  9. Gentoo - ssh-agent配置
  10. 【转】oracle数据库NUMBER数据类型
  11. 麦肯锡70页特辑报告论述《人工智能的未来之路》(完整版PPT)
  12. 系统集成的系统架构图的相关的vsd素材_信息系统集成专业技术知识:软件架构...
  13. 解决IIS占用CPU和内存大的问题
  14. 家谱处理 (30 分)(map映射)
  15. 电机学第一章(磁路的基本定律)
  16. 《疯狂的程序员》有感
  17. 红米AC2100刷固件心得
  18. (ONENET+阿里云+datav+node+js+MYSQL+STM32)基于ONENET的大数据可视化平台搭建
  19. 【Python 3.7】序数:序数表示位置,如 1st和 2nd。大多数序数都以 th结尾,只有 1、2和 3 例外。
  20. Dreamweaver构建Blog全程实录

热门文章

  1. 【转】 在内存中直接运行EXE类型的资源文件
  2. 什么是路由追踪,路由追踪有什么用?
  3. Unity OnPointerClick()鼠标左键无反应
  4. ostream这是啥玩意儿
  5. Web安全从入门到放弃之皮卡丘靶场精讲视频教程百度云下载链接(20201213整理)
  6. Java实战之亲戚关系计算器(swing版)(6)——实现计算功能
  7. 【大数据】Hadoop 体系(二)
  8. 线条方面的几个英文单词
  9. html中虚线怎么写,html中虚线的标签
  10. 独立开发者一个前端库月入2万刀 AMA