❶ android Matrix.setRotate 鍜 postRotate鐨勫尯鍒
Matrix涓昏佺敤浜庡瑰鉤闈㈣繘琛屽鉤縐(Translate)錛岀緝鏀(Scale)錛屾棆杞(Rotate)浠ュ強鏂滃垏(Skew)鎿嶄綔銆
涓虹畝鍖栫煩闃靛彉鎹錛孉ndroid灝佽呬簡涓緋誨垪鏂規硶鏉ヨ繘琛岀煩闃靛彉鎹錛涘叾涓鍖呮嫭錛
set緋誨垪鏂規硶錛歴etTranslate錛宻etScale錛宻etRotate錛宻etSkew錛涜劇疆錛屼細瑕嗙洊涔嬪墠鐨勫弬鏁般
pre緋誨垪鏂規硶錛歱reTranslate錛宲reScale錛宲reRotate錛宲reSkew錛涚煩闃靛厛涔橈紝濡侻' = M * T(dx, dy)銆
post緋誨垪鏂規硶錛歱ostTranslate錛宲ostScale錛宲ostRotate錛宲ostSkew錛涚煩闃靛悗涔橈紝濡侻' = T(dx, dy) * M銆
閫氳繃灝嗗彉鎹㈢煩闃典笌鍘熷嬬煩闃電浉涔樻潵杈懼埌鍙樻崲鐨勭洰鐨勶紝渚嬪傦細
騫崇Щ錛坸'=x+tx錛泍'=y+ty錛夛細
緙╂斁錛坸'=sx*x錛泍'=sy*y錛夛細
鏃嬭漿錛坸'=cos尾*x-sin尾*y錛泍'=sin尾*x+cos尾*y錛夛細
閫夋嫨闇瑕佺敤鍒板備笅鐨勪笁瑙掑嚱鏁扮殑鍏寮忥細
鈶爏in(偽+尾)=sin偽cos尾+cos偽sin尾
鈶cos(偽+尾)=cos偽cos尾-sin偽sin尾
鍏寮忊憼鍙浠ョ敱鍗曚綅鍦嗘柟娉曟垨鎵樺嫆瀵嗗畾鐞嗘帹瀵煎嚭鏉ャ
鎺ㄥ艱繃紼嬪弬瑙侊細http://blog.sina.com.cn/s/blog_58260f420100c03j.html
鏂滃垏錛坸'=x+k1*y錛泍'=k2*x+y錛夛細
//婧愮爜鏂囦歡錛歟xternal\skia\legacy\src\core\SkMatrix.cpp
#define SK_Scalar1 (1.0f)
#define kMatrix22Elem SK_Scalar1
typedef float SkScalar;
#define SkScalarMul(a, b) ((float)(a) * (b))
enum {
kMScaleX, kMSkewX, kMTransX,
kMSkewY, kMScaleY, kMTransY,
kMPersp0, kMPersp1, kMPersp2
};
void SkMatrix::reset() {
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //鍏跺間負1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //鍏跺礆紝鍏ㄤ負0
fMat[kMPersp2] = kMatrix22Elem; //鍏跺間負1
this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
}
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] = dx; //浠ユ柊鍊糳x瑕嗙洊鍘熷礆紝鍘熷兼棤鏁堜簡
fMat[kMTransY] = dy;
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //鍏跺間負1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //鍏跺礆紝鍏ㄤ負0
fMat[kMPersp2] = kMatrix22Elem; //鍏跺間負1
this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
} else {
this->reset();
}
}
bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->preConcat(m); //鐭╅樀鐨勫厛涔樿繍綆
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
SkScalarMul(fMat[kMSkewX], dy); //鍏堜箻錛岄渶瑕佺煩闃佃繍綆楄繃
fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
SkScalarMul(fMat[kMScaleY], dy);
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->postConcat(m); //鐭╅樀鐨勫悗涔樿繍綆
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += dx; //鍚庝箻錛岀洿鎺ュ姞鏂板糳x鍗沖彲
fMat[kMTransY] += dy;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::preConcat(
❷ Android 編程 如何實現 文字放大效果 例如圖片的放大和縮小的效果
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.ImageView;
public class MainActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
// 放大縮小
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
PointF start = new PointF();
PointF mid = new PointF();
float oldDist;
private ImageView myImageView;
// 模式
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myImageView = (ImageView) findViewById(R.id.myImage);
myImageView.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView myImageView = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
// 設置拖拉模式
case MotionEvent.ACTION_DOWN:
matrix.set(myImageView.getImageMatrix());
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
// 設置多點觸摸模式
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
break;
// 若為DRAG模式,則點擊移動圖片
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()
- start.y);
}
// 若為ZOOM模式,則點擊觸摸縮放
else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
// 設置碩放比例和圖片的中點位置
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
myImageView.setImageMatrix(matrix);
return true;
}
// 計算移動距離
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
// 計算中點位置
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}
❸ android畫一張圖片,縮放顯示並且放大不失真
這個問題涉及圖片呈現的一整套方案。歸納而言這個問題是:給定任意尺寸的圖片如何在任意尺寸解析度的機器上顯示?並且能夠保持圖片原來的清晰度。一般採用如下方案來解決這個問題:
1、首先給原圖片創建一塊內存緩存副本。如果不創建緩存的話,那麼任何一次圖片的剪切、縮放等操作都將丟失圖片信息,使得保持原有圖片的滋味那是不可能的。當然對於一般的程序而言,這個操作只需要調用簡單的API即可完成。例如Android,只需要創建一個對應圖片的Bitmap對象即可。
2、如果想要在設備顯示的初始化狀態圖片即為滿屏,那麼必須調用相關API動態獲得設備的解析度。然後按設備解析度的大小對圖片進行剪切並顯示到設備上。
注意:在獲得圖片解析度後,如果解析度大於圖片,那不用說,直接顯示圖片就好。但是如果小於圖片,此時有多種選擇。可以將圖片縮放至屏幕解析度(圖片縱橫比可能失真)也可以選擇剪切圖片的一部分顯示到屏幕上。
3、對圖片進行縮放或者移動
我們在圖片第一次顯示的時候無論是選擇縮放還是剪切,都要記錄下圖片被縮放的比例或者剪輯的范圍。這樣在用戶再次移動或者縮放的時候,根據之前的縮放比例和移動坐標,計算當前應該移動的位置和縮放比例。並且根據計算結果對緩存的圖片進行剪輯並顯示到屏幕上。
其實整個過程可以概括為如下流程:
——>圖片的初始縮放比例和顯示起點坐標——>用戶觸發縮放或者移動操作——>計算新的圖片縮放比例和顯示起點坐標——>根據新的縮放比例和顯示起點坐標剪輯緩存圖片並繪制到屏幕上......
❹ Android自定義控制項之可平移、縮放、旋轉圖片控制項
先上效果圖
單點拖動圖片對圖片進行平移操作。雙手縮放圖片大小和旋轉圖片到一定的角度。圖片縮放的時候 不能大於最大的縮放因子和小於最小的縮放因子。大於最大縮放因子或者小於最小縮放因子需要對圖像進行回彈。圖片旋轉的角度只能為90度的倍數,不滿足90度要進行回彈。圖片回彈要一個漸變的效果。
大體思路: 首先,Android中提供了Matrix類可以對圖像進行處理。其次,要顯示一張圖片最容易想到的就是ImageView。回彈要求漸變的過程,可以通過屬性動畫進行設置。所以大體的思路是:繼承ImageView,重寫onTouchEvent()方法,判斷事件類型,在對應的事件使用Matrix對圖像進行變換。
Matrix是一個已經封裝好的矩陣,最重要的作用就是對坐標點進行變換。
舉個栗子:
1.某個點(x0,y0,1)通過單位矩陣E映射得到的點還是(x0,y0,1)。
3.點(x0,y0,1)通過矩陣T映射得到的點就會做如下的變換
可以看到點(x0,y0,1)經過T矩陣在x軸方向上平移了dx,在y軸方向上平移了dy。
通過以上的變換可以得到具體的思路: 我們維護一個圖像對應的矩陣mCurrentMatrix,該矩陣主要是對ImageView中的圖像的各個點進行映射。ImageView在容器位置擺放完成之後,置mCurrentMatrix矩陣為單位矩陣。當onTouchEvent()方法中觸發單點觸控並且手指進行平移的時候,調用矩陣mCurrentMatrix的postTranslate(dx,dy),對mCurrentMatrix進行變換。當手指抬起,利用變換結束後的矩陣對圖像的各個點進行映射,從而得到平移變換後的圖像。同理可得,在兩只手指進行縮放旋轉的時候,我們對矩陣mCurrentMatrix進行各種變換,當縮放旋轉的事件結束再利用變換完的矩陣去映射圖像的各個點,從而得到縮放、旋轉後的圖像。
安卓自定義View進階 - Matrix原理
安卓自定義View進階 - Matrix詳解
首先理清事件的邏輯:
初始化圖像大小和位置
縮放圖像大小和控制項大小自適應,平移圖像中心和控制項中心重合
onTouchEvent()函數
平移操作
將圖像對應的矩陣進行變換。
縮放操作
mBoundRectF為記錄圖像邊界的矩形。縮放的時候選取圖像的中心進行縮放。
旋轉操作
旋轉的時候旋轉的旋轉中心也是圖像的中心
圖像中各個點的映射
調用ImageView的setImageMatrix(Matrix matrix)會讓ImageView根據設置的matrix去重新繪制圖像。
更新圖像的矩形邊界
獲得圖像的矩形,並根據矩陣映射矩形各個點的坐標。
縮放回彈
旋轉回彈
一些計算方法
要求圖像的變換是一個漸變的過程,很容易想到的就是屬性動畫。因為屬性動畫本身就是對值進行不斷set的過程。而我們維護的矩陣也是一個值,所以很自然可以想到,如果得到回彈之前的矩陣的值以及回彈之後矩陣的值,就可以根據動畫監聽器中動畫當前的系數值去改變矩陣的值。
對animator對象設置完監聽器之後,就可以在手指抬起的時候調用屬性動畫的start()方法開啟動畫。
自定義可平移、縮放、旋轉的控制項主要點有兩個方面:一是onTouchEvent()中判斷平移、旋轉、縮放的觸發條件,平移位移量、縮放比例因子、旋轉角度的計算。二是Matrix矩陣的應用。
❺ android等比例縮放圖片的方法
itmap icon = null;//原始圖片
int width = icon.getWidth(), height = icon.getHeight();
float scaleRate = 0.8f;//縮小的比例
while(width >= 300 || width >= 300) {
Matrix matrix = new Matrix();
matrix.postScale(width * scaleRate, height * scaleRate);
// 得到新的圖片
Bitmap newIcon = Bitmap.createBitmap(icon, 0, 0, width, height, matrix, true);
icon.recycle();
icon = newIcon;
width = icon.getWidth(), height = icon.getHeight();
}int width = icon.getWidth(), height = icon.getHeight();
if(width > 300 || width > 300) {
float scaleRate = width > height ? 300 / width : 300 / height;
Matrix matrix = new Matrix();
matrix.postScale(width * scaleRate, height * scaleRate);
// 得到新的圖片
Bitmap newIcon = Bitmap.createBitmap(icon, 0, 0, width, height, matrix, true);
icon.recycle();
icon = newIcon;
}
❻ android matrix涓 mappoints鏂規硶鍒板簳鏈変粈涔堢敤
閫氳繃 public int screenWidth錛 public int screenHeight錛 WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); screenWidth = display.getWidth(); screenHeight = display.getHeight(); 寰楀埌灞忓箷鐨勫藉拰楂 鐒跺悗鐢∕atrix鏂規硶閲岀殑緙╂斁鍑芥暟 鎶婅繖涓や釜鍊間綔涓哄弬鏁頒紶榪涘幓 鐒跺悗灝卞彲浠ュ疄鐜拌╁浘鐗囪嚜閫傚簲灞忓箷澶у皬浜