Android自定义View之布局(layout)缩放
2017-02-20 11:53
309 查看
需求:手指滑动布局放大缩小移动,其子控件也跟着放大缩小。
系统自带有放大缩小的控件:ZoomControls.控制一张图片的放大缩小很简单。但这不满足我们的需求。今天我们来完成对布局的放大缩小还有移动。先看效果图:
![](https://img-blog.csdn.net/20170220104517802?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHVvZHVvXzExMDEx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20170220104627533?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHVvZHVvXzExMDEx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1,首先准备工作:导入jar包,并add.
![](https://img-blog.csdn.net/20170220105056758?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHVvZHVvXzExMDEx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2,自定义PowerFullLayout继承FrameLayout ,注释都有 :
声明了一个变量:isScale,使用时要定义值。判断布局是否拦截此事件。
3,使用:项目中我使用了类似开关的一个imageview的点击事件,来判断是否拦截事件。看代码:
4,布局文件:
写博客的初心,其实就是记录一些在项目中使用到的一些技术,总结这些技术,方便今后阅读。
jar包下载地址:
http://download.csdn.net/download/duoduo_11011/9758507
系统自带有放大缩小的控件:ZoomControls.控制一张图片的放大缩小很简单。但这不满足我们的需求。今天我们来完成对布局的放大缩小还有移动。先看效果图:
1,首先准备工作:导入jar包,并add.
2,自定义PowerFullLayout继承FrameLayout ,注释都有 :
package com.skyworth.publicdisplay.view; import android.content.Context; import android.support.v4.widget.ViewDragHelper; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; import android.widget.FrameLayout; import com.nineoldandroids.view.ViewHelper; /** * ${DESC} * author: gyq * create at 2017/2/17 11:17 */ public class PowerFullLayout extends FrameLayout { // 屏幕宽高 private int screenHeight; private int screenWidth; private ViewDragHelper mDragHelper; private long lastMultiTouchTime;// 记录多点触控缩放后的时间 private int originalWidth;// view宽度 private int originalHeight;// view高度 private ScaleGestureDetector mScaleGestureDetector = null; // private View view; private int downX;// 手指按下的x坐标值 private int downY;// 手指按下的y坐标值 private int left;// view的左坐标值 private int top;// view的上坐标值 private int right;// view的右坐标值 private int bottom;// view的下坐标值 private int newHeight; private int newWidth; public boolean isScale = false; private float scale; private float preScale = 1;// 默认前一次缩放比例为1 public PowerFullLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public PowerFullLayout(Context context, AttributeSet attrs) { this(context, attrs,0); } public PowerFullLayout(Context context) { this(context,null); } private void init(Context context) { mDragHelper = ViewDragHelper.create(this, callback); mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); screenWidth = getMeasuredWidth(); screenHeight = getMeasuredHeight(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { super.onInterceptTouchEvent(ev); return isScale; } private boolean needToHandle=true; @Override public boolean onTouchEvent(MotionEvent event) { int pointerCount = event.getPointerCount(); // 获得多少点 if (pointerCount > 1) {// 多点触控, switch (event.getAction()) { case MotionEvent.ACTION_DOWN: needToHandle=true; break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_POINTER_2_UP://第二个手指抬起的时候 needToHandle=true; break; default: break; } return mScaleGestureDetector.onTouchEvent(event);//让mScaleGestureDetector处理触摸事件 } else { long currentTimeMillis = System.currentTimeMillis(); if (currentTimeMillis - lastMultiTouchTime > 200&&needToHandle) { // 多点触控全部手指抬起后要等待200毫秒才能执行单指触控的操作,避免多点触控后出现颤抖的情况 try { mDragHelper.processTouchEvent(event); } catch (Exception e) { e.printStackTrace(); } return true; } // } } return false; } private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { /** * 用于判断是否捕获当前child的触摸事件 * * @param child * 当前触摸的子view * @param pointerId * @return true就捕获并解析;false不捕获 */ @Override public boolean tryCaptureView(View child, int pointerId) { if (preScale > 1){ return true; } return false; } /** * 控制水平方向上的位置 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { if (left < (screenWidth - screenWidth * preScale) / 2) left = (int) (screenWidth - screenWidth * preScale) / 2;// 限制mainView可向左移动到的位置 if (left > (screenWidth * preScale - screenWidth) / 2) left = (int) (screenWidth * preScale - screenWidth) / 2;// 限制mainView可向右移动到的位置 return left; } public int clampViewPositionVertical(View child, int top, int dy) { if (top < (screenHeight - screenHeight * preScale) / 2) { top = (int) (screenHeight - screenHeight * preScale) / 2;// 限制mainView可向上移动到的位置 } if (top > (screenHeight * preScale - screenHeight) / 2) { top = (int) (screenHeight * preScale - screenHeight) / 2;// 限制mainView可向上移动到的位置 } return top; } }; public class ScaleGestureListener implements ScaleGestureDetector.OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { float previousSpan = detector.getPreviousSpan();// 前一次双指间距 float currentSpan = detector.getCurrentSpan();// 本次双指间距 if (currentSpan < previousSpan) { // 缩小 scale = preScale - (previousSpan - currentSpan) / 1000; } else { // 放大 scale = preScale + (currentSpan - previousSpan) / 1000; } // 缩放view if (scale > 0.5) { ViewHelper.setScaleX(PowerFullLayout.this, scale);// x方向上缩放 ViewHelper.setScaleY(PowerFullLayout.this, scale);// y方向上缩放 } return false; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { // 一定要返回true才会进入onScale()这个函数 return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { preScale = scale;// 记录本次缩放比例 lastMultiTouchTime = System.currentTimeMillis();// 记录双指缩放后的时间 } } }
声明了一个变量:isScale,使用时要定义值。判断布局是否拦截此事件。
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { super.onInterceptTouchEvent(ev); return isScale; }
3,使用:项目中我使用了类似开关的一个imageview的点击事件,来判断是否拦截事件。看代码:
windowLyt = (PowerFullLayout) findViewById(R.id.view_content); mScale = (ImageView)findViewById(R.id.iv_scale); mScale.setImageResource(R.drawable.scale_normal); mScale.setSelected(!mScale.isSelected()); ... //imageview的点击事件 case R.id.iv_scale : if (!mScale.isSelected()) { windowLyt.isScale = false; mScale.setImageResource(R.drawable.scale_normal); } else if (mScale.isSelected()) { windowLyt.isScale = true; mScale.setImageResource(R.drawable.scale_press); } mScale.setSelected(!mScale.isSelected()); break; ...
4,布局文件:
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical"> <com.skyworth.publicdisplay.view.PowerFullLayout android:id="@+id/view_content" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="1px" android:paddingLeft="2px" android:paddingTop="1px" /> </LinearLayout>
写博客的初心,其实就是记录一些在项目中使用到的一些技术,总结这些技术,方便今后阅读。
jar包下载地址:
http://download.csdn.net/download/duoduo_11011/9758507
相关文章推荐
- Android开发-将自定义View布局到Layout中并调用
- Android 自定义RecyclerView.ItemDecoration(GridLayoutManager布局下)
- Android学习个人笔记1-Layout界面布局-xml,java混合模式-自定义view
- android 使用TabLayout 自定义View布局作为底部菜单栏
- android实现自定义RelativeLayout可拖动、缩放、旋转TextView-更新版
- Android开发-将自定义View布局到Layout中并调用
- 【Android 如何置底一个View(附 前置声明layout布局文件中的资源ID)】
- android之自定义ViewGroup和自动换行的布局的实现
- Android开发中自定义View设定到FrameLayout布局中实现多组件显示
- android之自定义ViewGroup和自动换行的布局的实现
- ListView 自定义item布局 android.widget.LinearLayout$LayoutParams
- 在Android中,可以自定义类,继承ViewGroup等容器类,以实现自己需要的布局显示。
- Android开发中自定义View设定到FrameLayout布局中实现多组件显示
- ListView 自定义item布局 android.widget.LinearLayout$LayoutParams
- View在屏幕上显示出来要先经过measure(计算)和layout(布局)android
- 开源项目之Android ViewBadger(自定义的视图布局)
- Android自定义View研究(七)--XML中布局自定义View时View触摸原点问题
- Android的WindowManager.LayoutParams的多view和Toast的层布局
- Android自定义View以及layout属性全攻略
- Android自定义View设定到FrameLayout布局中实现多组件显示