使用 ShapeDrawable 实现小动画之图片🔍
常用函数
- setBounds():用来指定当前ShapeDrawable 在当前控件中的显示位置。
- getPaint();
- Paint.setShader():Shader 是从S h apeDrawab l e 所在区域的左上角开始绘制的。
代码实现
-
自定义 View
public class MyTelescopeView extends View { private Bitmap mBitmap; private ShapeDrawable mShapeDrawable; private int radius = 320; private int factor = 3; private Matrix mMatrix = new Matrix(); private Bitmap mDecodeResource; public MyTelescopeView(Context context) { super(context); init(); } public MyTelescopeView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public MyTelescopeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() {setLayerType(LAYER_TYPE_SOFTWARE, null);} /** * 通过 activity 向 自定义 View 传递参数; * @param radius 监听 SeekBar 的半径 * @param factor 监听 SeekBar 的放大倍率 * @param isFlush 是否需要刷新页面?只有 放大倍数发生改变才刷新页面(刷新放大镜), */ public void setParameter(int radius, int factor,boolean isFlush) { this.radius = radius; this.factor = factor; //解决,更新放大倍率、放大镜半径后,镜子位置岔劈的问题; if (isFlush)mBitmap = null; } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: final int x = (int) event.getX(); final int y = (int) event.getY(); //表示的是绘制 Shader 的起始位置 mMatrix.setTranslate(radius - factor * x, radius - factor * y); mShapeDrawable.getPaint().getShader().setLocalMatrix(mMatrix); // bounds,圆的外切矩形 mShapeDrawable.setBounds(x - radius, y - radius, x + radius, y + radius); invalidate(); break; case MotionEvent.ACTION_UP: mShapeDrawable.setBounds(-10, -10, 0, 0); invalidate(); break; default: break; } return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mBitmap == null) { mDecodeResource = BitmapFactory.decodeResource(getResources(), R.drawable.advance_woods_path); mBitmap = Bitmap.createScaledBitmap(mDecodeResource, getWidth(), getHeight(), false); BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(mBitmap, mBitmap.getWidth() * factor, mBitmap.getHeight() * factor, true), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mShapeDrawable = new ShapeDrawable(new OvalShape()); mShapeDrawable.getPaint().setShader(shader); } canvas.drawBitmap(mBitmap, 0, 0, null); mShapeDrawable.draw(canvas); } }
-
MainActivity.java
public class TelescopeActivity extends AppCompatActivity { private TextView tv_telescope_factor, tv_telescope_radius; private SeekBar sb_telescope_factor, sb_telescope_radius; private MyTelescopeView telescope_view; public int telescope_factor = 3; public int telescope_radius = 320; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_telescope); initView(); } private void initView() { …… sb_telescope_factor.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { telescope_factor = progress; tv_telescope_factor.setText(String.valueOf(progress)); sb_telescope_factor.setProgress(progress); telescope_view.setParameter(telescope_radius, telescope_factor,true); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); sb_telescope_radius.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { telescope_radius = progress; tv_telescope_radius.setText(String.valueOf(progress)); sb_telescope_radius.setProgress(progress); telescope_view.setParameter(telescope_radius, telescope_factor,false); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } }
注意
- 初始化在 onDraw() 方法中;通过
Bitmap.createScaledBitmap
方法根据源图像生成一个指定宽度和高度的 Bitmap;将源图像缩放到当前控件大小。 - 上述代码中表示的是绘制 Shader 的起始位置
mMatrix.setTranslate(radius - factor * x, radius - factor * y); mShapeDrawable.getPaint().getShader().setLocalMatrix(mMatrix);
- 关于项目存在一个 BUG,我调了一天……感兴趣的小伙伴,可以看这里:一个BUG调一天之图片放大镜。
Activity 向自定义 View 传递参数
- View 中定义 set 方法;
- 在 Activity 中实例化 View 调用其 set 方法;
声明:本文整理自《启舰_自定义控件》,如有侵权请联系我。