編輯:關於Android編程
標簽(空格分隔): Android基礎入門教程
在Canvas的API文檔中,我們看到這樣一個方法:drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
這個Matrix可是有大文章的,前面我們在學Paint的API中的ColorFilter中曾講過ColorMatrix
顏色矩陣,一個4 * 5 的矩陣,我們可以通過修改矩陣值來修改色調,飽和度等!
而今天講的這個Matrix可以結合其他API來控制圖形,組件的變換。比如Canvas就提供了上面的
這個drawBitmap來實現矩陣變換的效果!下面我們來慢慢研究這個東東~
官方API文檔:Matrix
setTranslate(float dx, float dy):控制Matrix進行平移 setRotate(float degrees, float px, float py):旋轉,參數依次是:旋轉角度,軸心(x,y) setScale(float sx, float sy, float px, float py):縮放,
參數依次是:X,Y軸上的縮放比例;縮放的軸心 setSkew(float kx, float ky):傾斜(扭曲),參數依次是:X,Y軸上的縮放比例
其實和Canvas變換的方法基本一致,在為Matrix設置了上面的變換後,調用Canvas的
drawBitmap()方法調用矩陣就好~
運行效果圖:
代碼實現:
MyView.java:
/**
* Created by Jay on 2015/11/11 0011.
*/
public class MyView extends View {
private Bitmap mBitmap;
private Matrix matrix = new Matrix();
private float sx = 0.0f; //設置傾斜度
private int width,height; //位圖寬高
private float scale = 1.0f; //縮放比例
private int method = 0;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init() {
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img_meizi);
width = mBitmap.getWidth();
height = mBitmap.getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (method){
case 0:
matrix.reset();
break;
case 1:
sx += 0.1;
matrix.setSkew(sx,0);
break;
case 2:
sx -= 0.1;
matrix.setSkew(sx,0);
break;
case 3:
if(scale < 2.0){
scale += 0.1;
}
matrix.setScale(scale,scale);
break;
case 4:
if(scale > 0.5){
scale -= 0.1;
}
matrix.setScale(scale,scale);
break;
}
//根據原始位圖與Matrix創建新圖片
Bitmap bitmap = Bitmap.createBitmap(mBitmap,0,0,width,height,matrix,true);
canvas.drawBitmap(bitmap,matrix,null); //繪制新位圖
}
public void setMethod(int i){
method = i;
postInvalidate();
}
}
布局代碼:activity_main.xml:
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button btn_reset;
private Button btn_left;
private Button btn_right;
private Button btn_zoomin;
private Button btn_zoomout;
private MyView myView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
}
private void bindViews() {
btn_reset = (Button) findViewById(R.id.btn_reset);
btn_left = (Button) findViewById(R.id.btn_left);
btn_right = (Button) findViewById(R.id.btn_right);
btn_zoomin = (Button) findViewById(R.id.btn_zoomin);
btn_zoomout = (Button) findViewById(R.id.btn_zoomout);
myView = (MyView) findViewById(R.id.myView);
btn_reset.setOnClickListener(this);
btn_left.setOnClickListener(this);
btn_right.setOnClickListener(this);
btn_zoomin.setOnClickListener(this);
btn_zoomout.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_reset:
myView.setMethod(0);
break;
case R.id.btn_left:
myView.setMethod(1);
break;
case R.id.btn_right:
myView.setMethod(2);
break;
case R.id.btn_zoomin:
myView.setMethod(3);
break;
case R.id.btn_zoomout:
myView.setMethod(4);
break;
}
}
}
用法非常簡單,就不解釋了~
在API文檔中還有這樣一個方法:
drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
int vertOffset, int[] colors, int colorOffset, Paint paint)參數依次是:
bitmap:需要扭曲的原位圖
meshWidth/meshHeight:在橫/縱向上把原位圖劃分為多少格
verts:長度為(meshWidth+1)*(meshHeight+2)的數組,他記錄了扭曲後的位圖各頂點(網格線交點)
位置,雖然他是一個一維數組,但是實際上它記錄的數據是形如(x0,y0),(x1,y1)..(xN,Yn)格式的數據,
這些數組元素控制對bitmap位圖的扭曲效果
vertOffset:控制verts數組從第幾個數組元素開始對bitmap進行扭曲(忽略verOffset之前數據
的扭曲效果)
代碼示例:
運行效果圖:
代碼實現:
/**
* Created by Jay on 2015/11/11 0011.
*/
public class MyView extends View {
//將水平和豎直方向上都劃分為20格
private final int WIDTH = 20;
private final int HEIGHT = 20;
private final int COUNT = (WIDTH + 1) * (HEIGHT + 1); //記錄該圖片包含21*21個點
private final float[] verts = new float[COUNT * 2]; //扭曲前21*21個點的坐標
private final float[] orig = new float[COUNT * 2]; //扭曲後21*21個點的坐標
private Bitmap mBitmap;
private float bH,bW;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init() {
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img_wuliao);
bH = mBitmap.getWidth();
bW = mBitmap.getHeight();
int index = 0;
//初始化orig和verts數組。
for (int y = 0; y <= HEIGHT; y++)
{
float fy = bH * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++)
{
float fx = bW * x / WIDTH;
orig[index * 2 + 0] = verts[index * 2 + 0] = fx;
orig[index * 2 + 1] = verts[index * 2 + 1] = fy;
index += 1;
}
}
//設置背景色
setBackgroundColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, verts
, 0, null, 0, null);
}
//工具方法,用於根據觸摸事件的位置計算verts數組裡各元素的值
private void warp(float cx, float cy)
{
for (int i = 0; i < COUNT * 2; i += 2)
{
float dx = cx - orig[i + 0];
float dy = cy - orig[i + 1];
float dd = dx * dx + dy * dy;
//計算每個座標點與當前點(cx、cy)之間的距離
float d = (float)Math.sqrt(dd);
//計算扭曲度,距離當前點(cx、cy)越遠,扭曲度越小
float pull = 80000 / ((float) (dd * d));
//對verts數組(保存bitmap上21 * 21個點經過扭曲後的座標)重新賦值
if (pull >= 1)
{
verts[i + 0] = cx;
verts[i + 1] = cy;
}
else
{
//控制各頂點向觸摸事件發生點偏移
verts[i + 0] = orig[i + 0] + dx * pull;
verts[i + 1] = orig[i + 1] + dy * pull;
}
}
//通知View組件重繪
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
//調用warp方法根據觸摸屏事件的座標點來扭曲verts數組
warp(event.getX(), event.getY());
return true;
}
}
實現流程分析:
首先你要弄清楚,這個verts數組存儲的是什麼?比如
verts[0]和verts1,這兩個相鄰的元素其實表示的就是我們第一個點的x坐標和y坐標!
知道這一點,你就知道為什麼有21 * 21個點,以及為什麼數組長度等於這個值 * 2!
初始化部分也就懂了!
接著我們再來看看根據觸摸事件計算verts數組元素的值的實現:
獲得觸摸點的x,y坐標,拿這個值去減對應點的x,y只,計算出觸摸點和每個坐標點的距離
然後計算所謂的扭曲度:80000 / ((float) (dd * d));扭曲度 >= 1的,直接讓該坐標
點指向這個觸摸點,< 1的,則讓各個頂點向觸摸點發生偏移,然後再調用invalidate()重繪~
大概就這樣~多思考思考,如果還是不理解就算了~知道有這東西就好!
原生應用不僅可以跳轉到RN頁面,也可以吧RN的組件放到原生應用中,作為原生應用的一部分。首先介紹如何把react native嵌入到android中,然後再介紹如何把RN
Android快捷方式解密Android快捷方式作為Android設備的殺手锏技能,一直都是非常重要的一個功能,也正是如此,各種流氓App也不斷通過快捷方式霸占著這樣一個
什麼是View?實現View滑動的方式有哪些?1. 關於View我們需要知道的(1)什麼是View? Android中的View類是所
本文實例為大家分享了Android實現蒙板效果的相關代碼,供大家參考,具體內容如下1、不保留標題欄蒙板的實現效果:原理:1、彈窗時,設置背景窗體的透明度2、取消彈窗時,恢