首先還是最基礎的ImageView控件如何顯示圖片:
<ImageView
Android:id="@+id/imgView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/ic_prepicture"
android:scaleType="matrix"
/>
以上布局中xml的代碼主要是scaleType的設置,決定了圖片初始顯示的狀態,ImageView.ScaleType設置圖解 這篇文章可以清楚的看到每個參數的效果。
這裡我們主要用matrix這個效果實現縮放,一定要設置scaleType為Matrix,才能實現相應的效果,也可以在代碼中imgView.setScaleType(ScaleType.MATRIX);如此設置。
直奔主題
第一步:了解操作對象(Matrix)以及操作方式(平移和縮放)
1, ImageView控件有getImageMatrix,setImageMatrix這兩個函數獲取/設置其像素矩陣Matrix;(這個就是我們要操作的對象)
2.1 矩陣Matrix又有如下的函數1:postTranslate(double dx, double dy)可以實現矩陣平移(dx, dy)它的API說明是:Postconcats the matrix with the specified translation. M' = T(dx, dy) * M。
2.2 函數2:postScale(float sx, float sy, float px, float py) 可以實現矩陣水平/垂直方向縮放sx,sy;同時控制縮放的中心點(px, py)API說明:Postconcats the matrix with the specified scale. M' = S(sx, sy, px, py) * M
第二步:了解如何獲取平移參數值(dx, dy)以及縮放參數值(sx, sy, centerPoint.x, centerPoint.y)
對於Android開發來說,這樣的實現應該很簡單,只是一個OnTouchListener類的實現,重寫public boolean onTouch(View v, MotionEvent event) 函數,其中平移是單指,縮放是多指
1, switch(event.getAction() & MotionEvent.ACTION_MASK),與MotionEvent.ACTION_MASK做與運算主要是為了多指消息的識別,不然不能響應多指。
2, 平移情況:比較簡單,直接在ACTION_MOVE實現中計算dx, dy(event.getX(), event.getY());
3, 縮放情況:需要計算兩個手指之間的距離dis1, dis2, 這樣scale = dis2/dis1; 同時還要算出兩個手指的中心點,作為縮放的中心點。
4,再次理一下思路:當出發Down的消息(手指按下)時候,記錄初始點的狀態;當響應Move的時候,將當前狀態與初始狀態作比較,做平移或者縮放的操作;當up的時候,初始化狀態。
第三步,通過前面的贅述,直接上代碼:
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
//單指按下
case MotionEvent.ACTION_DOWN:
{
mMode = DRAGMODE;
mStarPt.set(event.getX(), event.getY());
mCurrMatrix = mImageView.getImageMatrix();
break;
}
//多指縮放的按下
case MotionEvent.ACTION_POINTER_DOWN:
{
mMode = ZOOMMODE;
mStarDis = GetDistance(event);
mMidPt = GetMidPt(event);
mCurrMatrix = mImageView.getImageMatrix();
break;
}
//移動
case MotionEvent.ACTION_MOVE:
{
if(mMode == DRAGMODE)
{
float left = 0, top = 0, right = 0, bottom = 0;
float dx = event.getX() - mStarPt.x;
float dy = event.getY() - mStarPt.y;
mMatrix.set(mCurrMatrix);
mMatrix.postTranslate(dx, dy);
mStarPt.set(event.getX(), event.getY());
}
else if(mMode == ZOOMMODE)
{
float endDis = GetDistance(event);
if (endDis > 10f)
{
float fScale = endDis /mStarDis;
mMatrix.set(mCurrMatrix);
mMatrix.postScale(fScale, fScale, mMidPt.x, mMidPt.y);
//注意加上這一句,否則縮放為數量級了
mStarDis = endDis;
}
}
mImageView.setImageMatrix(mMatrix);
break;
}
//單指抬起
case MotionEvent.ACTION_UP:
//多指抬起
case MotionEvent.ACTION_POINTER_UP:
{
mMode = 0;
break;
}
}
return true;
}
以下是全局變量的定義:
private ImageView mImageView;
private int mMode; //模式:1-拉動;2-縮放
final private int DRAGMODE = 1;
final private int ZOOMMODE = 2;
private PointF mStarPt = new PointF();
private float mStarDis;
private PointF mMidPt = new PointF();
private Matrix mMatrix = new Matrix();
private Matrix mCurrMatrix = new Matrix();
這樣就實現了簡單的縮放和平移操作了,代碼思路還是參考了網上的一些博客文章。
但是,這樣還是有一個問題,就是縮放的限制,不能無限大,也不能無限小,平移也需要定義范圍內的平移。下一章就要講如何實現圖片浏覽器中的效果。到時再將整體代碼貼上來。
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11