Android仿酷狗面板預覽介面的實現(利用canvas縮放的原理)
一直好奇酷狗的面板預覽是怎麼實現的。
難道是另外寫了一個一模一樣的佈局檔案,只是寬高不一樣?
感覺賊吉爾神奇啊!

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
想想還是覺得不可能是一個個控制元件寫上去的,一定有某種極其神奇卻簡單的方法。
方法就是

在這裡插入圖片描述
/** * Preconcat the current matrix with the specified scale. * * @param sx The amount to scale in X * @param sy The amount to scale in Y */ public void scale(float sx, float sy) { native_scale(mNativeCanvasWrapper, sx, sy); } /** * Preconcat the current matrix with the specified scale. * * @param sx The amount to scale in X * @param sy The amount to scale in Y * @param px The x-coord for the pivot point (unchanged by the scale) * @param py The y-coord for the pivot point (unchanged by the scale) */ public final void scale(float sx, float sy, float px, float py) { translate(px, py); scale(sx, sy); translate(-px, -py); }
//x縮放比例,y縮放比例,px,py,縮放中心點,可以設定左頂點或者中心等頂點
canvas.scale(scale, scale, px, py);
只需要2步就能實現仿酷狗面板預覽縮放效果:
1.先測量期望縮放至的寬高,然後將寬高設定為被縮放View的寬高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); width_self=getMeasuredWidth(); height_self=getMeasuredHeight(); super.onMeasure(MeasureSpec.makeMeasureSpec( width_bigview, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height_bigview, MeasureSpec.EXACTLY)); }
2.計算scale縮放比例,如果以寬為基準縮放,那就是期望縮放至的寬度/被縮放View的寬度;如果以高為基準縮放,同理
@Override protected void dispatchDraw(Canvas canvas) { if (basedOnWidthOrHeight) { scale = (width_self - getPaddingTop() - getPaddingBottom()) * 1f / width_bigview; } else { scale = (height_self - getPaddingTop() - getPaddingBottom()) * 1f / height_bigview; } PaintFlagsDrawFilter pfd= new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG); /** * 對canvas設定抗鋸齒的濾鏡,防止變化canvas引起畫質降低 */ canvas.setDrawFilter(pfd); canvas.save(); //x縮放比例,y縮放比例,px,py,縮放中心點,可以設定左頂點或者中心等頂點 canvas.scale(scale, scale, px, py); super.dispatchDraw(canvas); canvas.restore(); }
在這裡插入程式碼片
上圖:模擬器截圖有點模糊,真實手機是沒毛病的

在這裡插入圖片描述
以中心點 為縮放中心

在這裡插入圖片描述
以左頂點為縮放中心

在這裡插入圖片描述
完整程式碼:

在這裡插入圖片描述
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/iv" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:scaleType="centerInside" android:src="@drawable/pic" /> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="縮放佈局" /> </LinearLayout>
public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startAppcompatActivity(ScaleViewActivity.class); } }); } @Override public void onClick(View v) { } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_scale_view" android:layout_width="match_parent" android:layout_height="match_parent"> </RelativeLayout>
public class ScaleViewActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scale_view); View layout = LayoutInflater.from(this).inflate(R.layout.activity_main, null); ScaleFrameLayout scaleFrameLayout = new ScaleFrameLayout(this); scaleFrameLayout.setLayoutParams(new RelativeLayout.LayoutParams(500,1300)); scaleFrameLayout.addView(layout); //scaleFrameLayout.config(false, ScreenUtils.getScreenWidth(this),ScreenUtils.getScreenHeight(this), //ScreenUtils.getScreenWidth(this)/2,ScreenUtils.getScreenHeight(this)/2); scaleFrameLayout.config(false, ScreenUtils.getScreenWidth(this),ScreenUtils.getScreenHeight(this),0,0); RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.activity_scale_view); relativeLayout.addView(scaleFrameLayout); } }
public class ScaleFrameLayout extends FrameLayout { private float scale = 1f; private int width_self, height_self; private int width_bigview = 0, height_bigview = 0; private boolean basedOnWidthOrHeight = true;//預設基於寬度,按比例縮放 private Context context; private float px,py;//縮放中心點 public ScaleFrameLayout(Context context) { super(context); this.context = context; } public ScaleFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public void config(boolean basedOnWidthOrHeight,int width_bigview, int height_bigview,float px, float py) { this.basedOnWidthOrHeight=basedOnWidthOrHeight; this.width_bigview = width_bigview; this.height_bigview = height_bigview; if (this.width_bigview == 0) this.width_bigview = ScreenUtils.getScreenWidth(context); if (this.height_bigview == 0) this.height_bigview = ScreenUtils.getScreenHeight(context); this.px=px; this.py=py; invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); width_self=getMeasuredWidth(); height_self=getMeasuredHeight(); super.onMeasure(MeasureSpec.makeMeasureSpec( width_bigview, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height_bigview, MeasureSpec.EXACTLY)); } @Override protected void dispatchDraw(Canvas canvas) { if (basedOnWidthOrHeight) { scale = (width_self - getPaddingTop() - getPaddingBottom()) * 1f / width_bigview; } else { scale = (height_self - getPaddingTop() - getPaddingBottom()) * 1f / height_bigview; } PaintFlagsDrawFilter pfd= new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG); /** * 對canvas設定抗鋸齒的濾鏡,防止變化canvas引起畫質降低 */ canvas.setDrawFilter(pfd); canvas.save(); //x縮放比例,y縮放比例,px,py,縮放中心點,可以設定左頂點或者中心等頂點 canvas.scale(scale, scale, px, py); super.dispatchDraw(canvas); canvas.restore(); } }

在這裡插入圖片描述
各位老鐵有問題歡迎及時聯絡、指正、批評、撕逼
關注專題Android開發常用開源庫
微信公眾號
這裡寫圖片描述
QQ群
這裡寫圖片描述