精华内容
下载资源
问答
  • 由图②可知,当一阶函数在某点(即驻点)处为0,二阶函数在该点处大于0时,原函数在该驻点处取极小值; 由图③④可知,当一阶函数在某点(即驻点)处为0,二阶函数在该点处也为0,且以该点加减个非常小的...

    在这里插入图片描述
    在这里插入图片描述

    • 由图①可知,当一阶导函数在某点(即驻点)处为0,二阶导函数在该点处小于0时,原函数在该驻点处取极大值;
    • 由图②可知,当一阶导函数在某点(即驻点)处为0,二阶导函数在该点处大于0时,原函数在该驻点处取极小值;
    • 由图③④可知,当一阶导函数在某点(即驻点)处为0,二阶导函数在该点处也为0,且以该点加减一个非常小的δx得到两点,二阶导函数在这两点处的值异号时,该驻点为原函数的鞍点;
    • 由图⑤可知,当一阶导函数在某点(即驻点)处为0,二阶导函数在该点处也为0,且以该点加减一个非常小的δx得到两点,二阶导函数在这两点处的值同号且都大于0时,该驻点为原函数的极小值点;
    • 由图⑥可知,当一阶导函数在某点(即驻点)处为0,二阶导函数在该点处也为0,且以该点加减一个非常小的δx得到两点,二阶导函数在这两点处的值同号且都小于0时,该驻点为原函数的极大值点;
    • 当驻点处二阶导数为0时,还可求其三阶导、四阶导等,直到可以判断出原函数在驻点是极小值点、极大值点还是鞍点为止。
    展开全文
  • 关于曲线的、二、三阶的总结

    千次阅读 2020-05-11 19:49:04
    二阶导数可以用来判断函数在段区间上的凹凸性,二阶导大于零,是凹的,小于零是凸的。 三阶导数一般不用,可以用来找函数的拐点,拐点的意思是如果曲线f(x)在经过点(x0,f(x0))时,曲线的凹凸性改变了,那么就称这...

    最近在做光条中心线提取方面的工作,由于激光光条符合高斯模型,高斯模型又是一个近似抛物线的二维曲线。在求解光条中心的过程中要求解曲线的极值之类的问题,与曲线的导数相关,所以总结一下相关的内容。
    一阶导数可以用来描述原函数的增减性。区间内,一阶导数大于零,单增,一阶导数小于零,单减。
    二阶导数可以用来判断函数在一段区间上的凹凸性,二阶导大于零,是凹的,小于零是凸的。
    三阶导数一般不用,可以用来找函数的拐点,拐点的意思是如果曲线f(x)在经过点(x0,f(x0))时,曲线的凹凸性改变了,那么就称这个点为曲线的拐点。若f(x)在x0的某邻域内具有三阶连续导数,f’’(x0)=0,f’’’(x0)≠0,那么(x0,f(x0))是f(x)的一个拐点。

    二阶导数的性质:
    (1)如果一个函数f(x)在某个区间I上有f’’(x)(即二阶导数)>0恒成立,那么对于区间I上的任意x,y,总有:
    f(x)+f(y)≥2f[(x+y)/2],如果总有f’’(x)<0成立,那么上式的不等号反向。
    几何的直观解释:如果一个函数f(x)在某个区间I上有f’’(x)(即二阶导数)>0恒成立,那么在区间I上f(x)的图象上的任意两点连出的一条线段,这两点之间的函数图象都在该线段的下方,反之在该线段的上方。
    (2)判断函数极大值以及极小值。
    结合一阶、二阶导数可以求函数的极值。当一阶导数等于0,而二阶导数大于0时,为极小值点。当一阶导数等于0,而二阶导数小于0时,为极大值点;当一阶导数和二阶导数都等于0时,为驻点。

    在微积分,驻点又称为平稳点、稳定点或临界点是函数的一阶导数为零,即在**“这一点”,函数的输出值停止增加或减少**。对于一维函数的图像,驻点的切线平行于x轴。对于二维函数的图像,驻点的切平面平行于xy平面。值得注意的是,一个函数的驻点不一定是这个函数的极值点(考虑到这一点左右一阶导数符号不改变的情况);反过来,在某设定区域内,一个函数的极值点也不一定是这个函数的驻点(考虑到边界条件)。函数的一阶导数为0的点(驻点也称为稳定点,临界点)。对于多元函数,驻点是所有一阶偏导数都为零的点。

    展开全文
  • 我们曾在帖子讨论过,个连续函数可但是函数不连续的个例子: http://www.cnblogs.com/zhangwenbiao/p/5426699.html 此函数为$g(x)=x^{2}\sin \left(\frac{1}{x}\right)$,补充定义$g(0)=0$. 可计算得$g'(0)...

    我们曾在帖子讨论过,一个连续函数可导但是导函数不连续的一个例子:

    http://www.cnblogs.com/zhangwenbiao/p/5426699.html

    此函数为$g(x)=x^{2}\sin \left(\frac{1}{x}\right)$,补充定义$g(0)=0$. 可计算得$g'(0)=0$

    我们定义函数

    $$f(x)=\epsilon x+x^{2}\sin \left(\frac{1}{x}\right)$$

    补充定义$f(0)=0$.则

    $$f'(0)=\epsilon$$

    取$1>\epsilon>0$, 当$x\neq 0$时,

    $$f'(x)=\epsilon+2x\sin \left(\frac{1}{x}\right)-\cos \left(\frac{1}{x}\right)$$

    取$x_{k}=\frac{1}{k\pi}$,

    $$f'(x_{k})=\epsilon-(-1)^{k}, k=1,2,3,\cdots$$

    因此, 包含零的区间导数符号无法取得一致,非单调函数。

    问题:此函数极值点如何?

     

    转载于:https://www.cnblogs.com/zhangwenbiao/p/5631731.html

    展开全文
  • Android自定义览地图组件()

    千次阅读 热门讨论 2017-08-21 09:31:52
    鉴于Android关于自定义览地图的相关资料以及开源项目贫乏,应Android同行几位小伙伴们的建议,决定写下这篇文章分享给大家。由于博客篇幅限制,本文将分两到三篇博文叙述。

    版权说明 : Android自定义导览地图组件(一)于当前CSDN博客乘月网属同一原创,转载请说明出处,谢谢。


             鉴于Android关于自定义导览地图的相关资料以及开源项目贫乏,应Android同行几位小伙伴们的建议,决定写下这篇文章分享给大家。由于博客篇幅限制,本文将分两到三篇博文叙述。
    进入主题:

             先看看下面的效果图:

             

             可以看到,地图组件基本上实现当前主流地图应用(如百度,高德地图)的缩放拖拽移动以及定位图标等功能。
    实现思路:
             其实一开始想了很多方案:
             1. 单纯的自定义一个View然后Draw绘制地图和定位图标,用各种分工逻辑类拆分单元实现。
             2. 自定义View绘制地图+自定义View绘制定位图标,用各种分工逻辑类拆分单元实现。
             3. 自定一个View,地图是View的背景图+ImageView作为定位图标。
             4. 自定义ViewGroup+自定义Imageview作为地图+ImageView作为定位图标。
             ………….省略后面n种方案,真是绞尽脑汁
             由于本文重点在于提供实现路线,最终敲定了最简单的第4种方案:自定义ViewGroup(MapContainer)+自定义ImageView(MapView)+ImageView(定位图标marker)。不过,通过本文的学习,上述其它方案的实现也就变得简单多了。
    分析:
             1. MapContainer提供地图和定位图标的盛放容器,定位图标可以叠加显示于地图之上。我们知道,地图的缩放(缩放会导致定位位置的改变)和移动,定位图标随之移动,作为ViewGroup肯定可以拿到这两种ImageView的对象,一边监听地图View----MapView的变化(获取变化值),再传递并控制地位图标View--marker的显示位置。
             2. 为什么自定义ImageView?因为ImageView可以直接显示地图图片呗,但是缩放移动什么的还得靠自定义来实现。
             3. 定位图标没什么难点,直接用ImageView显示坐标icon就好了,剩下的交给ViewGroup动态控制其位置就好了。
             通过上述,总结下该方案:核心业务就在MapView上,MapContainer打辅助,定位图标ImageView打酱油。
             对于一个图片可移动,缩放的功能实现,自然而然就能想到就是常见的查看大图嘛。
             开干!!!

    一、 自定义MapView
             图片加载完成时,自动对图片进行自适应ViewGroup(或屏幕)缩放。
             大多数情况下,图片分辨率都不会是刚好ViewGroup(或屏幕)大小,需要在图片加载时获取其真实显示尺寸并根据当前ViewGroup尺寸做自适应缩放以达到最佳的观感效果。
             那么如何知道图片什么时候加载好了?这里可以实现ViewTreeObserver. OnGlobalLayoutListener接口来订阅监听布局变化。当前视图树中,全局布局发生改变或者某个视图的可视状态发生改变时,会得到消息推送(调用订阅者的OnGlobalLayoutListener下的onGlobalLayoutListener方法),图片加载完成后显示到屏幕上便会触发该方法,完整代码如下:
    package cn.icheny.guide_map;
    
    import android.content.Context;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.view.ViewTreeObserver;
    import android.widget.ImageView;
    
    /**
     * 可手势缩放移动双击缩放ImageView
     *
     * @author www.icheny.cn
     * @date 2017/8/15
     */
    
    public class MapView extends ImageView implements ViewTreeObserver.OnGlobalLayoutListener {
    
        public MapView(Context context) {
            this(context, null);
        }
    
        public MapView(Context context, AttributeSet attrs) {
            this(context, null, 0);
        }
    
        public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            //订阅布局监听
            getViewTreeObserver().addOnGlobalLayoutListener(this);
        }
    
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            //取消订阅
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        }
    
        /**
         * 订阅者的onGlobalLayout方法,监听布局变化
         */
        @Override
        public void onGlobalLayout() {
    
        }
    }
              对于ImageView可缩放,需要设置:setScaleType(ScaleType.MATRIX)属性 ,初始化图片矩阵Matrix 对象以及设定三个缩放比例系数:
    ……
    float SCALE_MIN = 0.5f;//最小缩小比例值系数
    float SCALE_ADAPTIVE = 1f;//自适应ViewGroup(或屏幕)缩放比例值
    float SCALE_MID = 2f;//中间放大比例值系数,双击一次的放大值
    float SCALE_MAX = 4f;//最大放大比例值系数,双击两次的放大值
    private Matrix mScaleMatrix;//缩放矩阵
    
    public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setScaleType(ScaleType.MATRIX);
        mScaleMatrix = new Matrix();
    }
    ……
             正如上述,onGlobalLayout()在很多情况下都会被触发,然而我们只需要确定一旦图片加载完成便对其自适应屏幕的缩放处理,所以我们需要一个Flag进行判定,并确定能够获取Drawable对象则表示图片刚好加载完成:
    ……
    private boolean isPicLoaded = false;//图片是否已加载
    
    /**
     * 订阅者的onGlobalLayout函数
     */
    @Override
    public void onGlobalLayout() {
        if (!isPicLoaded) {
            Drawable drawable = getDrawable();
            if (null == drawable) {//图片不存在就继续监听
                return;
            }
            isPicLoaded=true;//图片存在,已加载完成,停止监听
            
        }
    }
    ……

             OK,检测到图片加载完成,便可以进行缩放处理。为了少点废话,接下来“代码+注释”为主:

        /**
         * 订阅者的onGlobalLayout函数
         */
        @Override
        public void onGlobalLayout() {
            if (!isPicLoaded) {
                Drawable drawable = getDrawable();
                if (null == drawable) {//图片不存在就继续监听
                    return;
                }
                isPicLoaded = true;//图片存在,已加载完成,停止监听
                //获取图片固有的宽高(不是指本身属性:分辨率,因为android系统在加载显示图片前可能对其压缩)
                int iWidth = drawable.getIntrinsicWidth();
                int iHeight = drawable.getIntrinsicHeight();
    
                //获取当前View(ImageView)的宽高,即父View给予的宽高
                int width = getWidth();
                int height = getHeight();
    
                //对比图片宽高和当前View的宽高,针对性的缩放
                if (iWidth >= width && iHeight <= height) {//如果图片固宽大于View宽,固高小于View高,
                    SCALE_ADAPTIVE = height * 1f / iHeight;   // 那么只需针对高度等比例放大图片(这里有别于查看大图的处理方式)
                } else if (iWidth <= width && iHeight >= height) {//固宽小于View宽,固高大于View高,针对宽度放大
                    SCALE_ADAPTIVE = width * 1f / iWidth;
                } else if (iWidth >= width && iHeight >= height || iWidth <= width && iHeight <= height) {//固宽和固高都大于或都小于View的宽高,
                    SCALE_ADAPTIVE = Math.max(width * 1f / iWidth, height * 1f / iHeight);//只取对宽和对高之间最小的缩放比例值(这里有别于查看大图的处理方式)
                }
    
                //先将图片移动到View中心位置
                mScaleMatrix.postTranslate((width - iWidth) * 1f / 2, (height - iHeight) * 1f / 2);
                //再对图片从View的中心点缩放
                mScaleMatrix.postScale(SCALE_ADAPTIVE, SCALE_ADAPTIVE, width * 1f / 2, height * 1f / 2);
                //执行偏移和缩放
                setImageMatrix(mScaleMatrix);
    
                //根据当前图片的缩放情况,重新调整图片的最大最小缩放值
                SCALE_MAX *= SCALE_ADAPTIVE;
                SCALE_MID *= SCALE_ADAPTIVE;
                SCALE_MIN *= SCALE_ADAPTIVE;
            }
        }

             折腾完自适应,开始折腾手势缩放,实现缩放手势探测器接口OnScaleGestureListener来完成图片随手势的动态缩放。初始化ScaleGestureDetector对象并重写当前View的onTouchEvent()方法,将touch事件交给ScaleGestureDetector处理:

    ……
    private ScaleGestureDetector mScaleGestureDetector;//缩放手势探测测器
    
    public MapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setScaleType(ScaleType.MATRIX);
        mScaleMatrix = new Matrix();
        mScaleGestureDetector = new ScaleGestureDetector(context, this);
    }
    
    /**
     * 缩放手势开始时调用该方法
     *
     * @param detector
     * @return
     */
    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        //返回为true,则缩放手势事件往下进行,否则到此为止,即不会执行onScale和onScaleEnd方法
        return true;
    }
    
    /**
     * 缩放手势进行时调用该方法
     * 缩放控制范围:SCALE_MIN——SCALE_MAX
     *
     * @param detector
     */
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        return true;
    }
    
    /**
     * 缩放手势完成后调用该方法
     *
     * @param detector
     */
    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
    
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mScaleGestureDetector != null) {
            //绑定缩放手势探测器,由其处理touch事件
            mScaleGestureDetector.onTouchEvent(event);
        }
        return true;
    }
    ……

             接下来是处理onScale事件代码:

        /**
         * 缩放手势进行时调用该方法
         * 缩放控制范围:SCALE_MIN——SCALE_MAX
         *
         * @param detector
         */
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            if (getDrawable() == null) {
                return true;//没有图片就不用折腾了
            }
            //缩放因子(即将缩放的值)
            float scaleFactor = detector.getScaleFactor();
            //当前图片已缩放的值(如果onScale第一次被调用,scale就是自适应后的缩放值:SCALE_ADAPTIVE)
            float scale = getDrawableScale();
            //当前缩放值在最大放大值以内且手势检测缩放因子为缩小手势(小于1),或当前缩放值在最小缩小值以内且缩放因子为放大手势,允许缩放
            if (scale <= SCALE_MAX && scaleFactor < 1 || scale >= SCALE_MIN && scaleFactor > 1) {
                //进一步考虑即将缩小后的缩放比例(scale*scaleFactor)低于规定SCALE_MIN-SCALE_MAX范围的最小值SCALE_MIN
                if (scale * scaleFactor < SCALE_MIN && scaleFactor < 1) {
                    //强制锁定缩小后缩放比例为SCALE_MIN(scale*scaleFactor=SCALE_MIN)
                    scaleFactor = SCALE_MIN / scale;
                }
                //进一步考虑即将放大后的缩放比例(scale*scaleFactor)高于规定SCALE_MIN-SCALE_MAX范围的最大值SCALE_MAX
                if (scale * scaleFactor > SCALE_MAX && scaleFactor > 1) {
                    //强制锁定放大后缩放比例为SCALE_MAX(scale*scaleFactor=SCALE_MAX)
                    scaleFactor = SCALE_MAX / scale;
                }
                //设定缩放值和缩放位置,这里缩放位置便是手势焦点的位置
                mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
                //执行缩放
                setImageMatrix(mScaleMatrix);
            }
            return true;
        }

              好了,写了那么多,上个图看看运行效果,舒缓下紧张的气氛:

              

              还是有效果的,滋滋滋~  不过,这个白边还有图片中心缩放着缩放着就跑偏了着实让人强迫症大发。所以,应该在执行缩放前调用checkBoderAndCenter()方法用于检测并修复留白边,图片中心跑偏的问题:

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
    ……
            //设定缩放值和缩放位置,这里缩放位置便是手势焦点的位置
            mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
    
            //检查即将缩放后造成的留空隙和图片不居中的问题,及时调整缩放参数
            checkBoderAndCenter();
    
            //执行缩放
            setImageMatrix(mScaleMatrix);
        }
        return true;
    }
    
    /**
     * 处理缩放和移动后图片边界与屏幕有间隙或者不居中的问题
     */
    private void checkBoderAndCenter() {
        RectF rect = getMatrixRect();
        int width = getWidth();
        int height = getHeight();
    
        float deltaX = 0;//X轴方向偏移量
        float deltaY = 0;//Y轴方向偏移量
    
        //图片宽度大于等于View宽
        if (rect.width() >= width) {
            //图片左边坐标大于0,即左边有空隙
            if (rect.left > 0) {
                //向左移动rect.left个单位到View最左边,rect.left=0
                deltaX = -rect.left;
            }
            //图片右边坐标小于width,即右边有空隙
            if (rect.right < width) {
                //向右移动width - rect.left个单位到View最右边,rect.right=width
                deltaX = width - rect.right;
            }
        }
        //图片高度大于等于View高,同理
        if (rect.height() >= height) {
            //图片上面坐标大于0,即上面有空隙
            if (rect.top > 0) {
                //向上移动rect.top个单位到View最上边,rect.top=0
                deltaY = -rect.top;
            }
            //图片下面坐标小于height,即下面有空隙
            if (rect.bottom < height) {
                //向下移动height - rect.bottom个单位到View最下边,rect.bottom=height
                deltaY = height - rect.bottom;
            }
        }
    
        //图片宽度小于View宽
        if (rect.width() < width) {
            //计算需要移动到X方向View中心的距离
            deltaX = width * 1f / 2 - rect.right + rect.width() * 1f / 2;
        }
    
        //图片高度小于View高度
        if (rect.height() < height) {
            //计算需要移动到Y方向View中心的距离
            deltaY = height * 1f / 2 - rect.bottom + rect.height() * 1f / 2;
        }
        mScaleMatrix.postTranslate(deltaX, deltaY);
    }
    
    /**
     * 根据当前图片矩阵变换成的四个角的坐标,即left,top,right,bottom
     *
     * @return
     */
    private RectF getMatrixRect() {
        RectF rect = new RectF();
        Drawable drawable = getDrawable();
        if (drawable != null) {
            rect.set(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        }
        mScaleMatrix.mapRect(rect);
        return rect;
    }

              效果图不贴了,节省写博时间。上图我们也可以看到:图片缩小到宽高小于View的宽高后,手指离开屏幕,此时图片无法自动恢复(放大)到自适应View宽高的大小,只能依靠手动缩放恢复,甚是心累。所以,需求来了…...缩放之后,检测这样的情况,再用一个动画让图片平滑恢复自适应View大小,接下来onScaleEnd登场:

        /**
         * 缩放手势完成后调用该方法
         *
         * @param detector
         */
        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            Drawable drawable = getDrawable();
            if (drawable == null) return;
            //当前缩放值
            float scale = getDrawableScale();
            //当前缩放值小于自适应缩放缩放比例,即图片小于View宽高
            if (scale < SCALE_ADAPTIVE) {
                postDelayed(new AutoScaleTask(SCALE_ADAPTIVE, getWidth() * 1f / 2, getHeight() * 1f), 2);
            }
        }
    
        /**
         * 自动缩放任务
         */
        private class AutoScaleTask implements Runnable {
            float targetScale;//目标缩放值
            float x;//缩放焦点的x坐标
            float y;//缩放焦点的y坐标
            static final float TMP_AMPLIFY = 1.05f;//放大梯度
            static final float TMP_SHRINK = 0.96f;//缩小梯度
            float tmpScale = 1.0f;//缩小梯度
    
            public AutoScaleTask(float targetScale, float x, float y) {
                this.targetScale = targetScale;
                this.x = x;
                this.y = y;
                //当前缩放值小于目标缩放值,目标是放大图片
                if (getDrawableScale() < targetScale) {
                    //设定缩放梯度为放大梯度
                    tmpScale = TMP_AMPLIFY;
                } else {  //当前缩放值小于(等于可以忽略)目标缩放值,目标是缩小图片
                    //设定缩放梯度为缩小梯度
                    tmpScale = TMP_SHRINK;
                }
            }
    
            @Override
            public void run() {
                //设定缩放参数
                mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
                //检查即将缩放后造成的留空隙和图片不居中的问题,及时调整缩放参数
                checkBoderAndCenter();
                setImageMatrix(mScaleMatrix);
                //当前缩放值
                float scale = getDrawableScale();
                //如果tmpScale>1即放大任务状态,且当前缩放值还是小于目标缩放值或
                // tmpScale<1即缩小任务状态,且当前缩放值还是大于目标缩放值就继续执行缩放任务
                if (tmpScale > 1 && scale < targetScale || scale > targetScale && tmpScale < 1) {
                    postDelayed(this, 2);
                } else {//缩放的略微过头了,需要强制设定为目标缩放值
                    tmpScale = targetScale / scale;
                    mScaleMatrix.postScale(tmpScale, tmpScale, x, y);
                    checkBoderAndCenter();
                    setImageMatrix(mScaleMatrix);
                }
            }
        }

              好了,大工造成!来看看效果吧:

               

              上面所述的留白,图片中心移位以及缩小后不能自动恢复自适应View(或屏幕)大小的问题在效果图中已经不复存在了,滋滋滋~

              上文代码提到自动缩放任务AutoScaleTask,咱趁热打铁来实现双击缩放功能。一般查看地图(或大图)时,双击,如果当前缩放比例小于一级放大(scale<SCALE_MID)比例就自动放大到一级放大(SCALE_ MID), 如果比例大于等于一级放大(SCALE_ MID)比例且小于二级放大(SCALE_MAX)比例就自动放大到二级放大(SCALE_MAX),如果等于二级放大(SCALE_ MID)比例就缩小到自适应View大小(SCALE_ADAPTIVE),在自动缩放过程中不再响应双击事件,直到自动缩放结束,这就意味着需要一个flag进行锁定。思路已经很清晰,就差Android手势探测器GestureDetector帮我们判断双击手势。嗯,是这样!贴代码:

    ……
    private boolean isAutoScaling = false;//是否处于自动缩放中,用于是否响应双击手势的flag
    private GestureDetector mGestureDetector;//手势探测器
    public ZoomImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    ……
        mGestureDetector = initGestureDetector(context);
    }
    
    /**
     * 初始化手势探测器
     *
     * @param context
     * @return GestureDetector
     */
    private GestureDetector initGestureDetector(Context context) {
        GestureDetector.SimpleOnGestureListener listner = new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                if (!isAutoScaling) {//如果不在自动缩放
                    isAutoScaling = true;
                    float x = e.getX();//双击触点x坐标
                    float y = e.getY();//双击触点y坐标
                    float scale = getDrawableScale();
                    if (scale < SCALE_MID) {//当前缩放比例小于一级缩放比例
                        //一级放大
                        postDelayed(new AutoScaleTask(SCALE_MID, x, y), 10);
                    } else if (scale >= SCALE_MID && scale < SCALE_MAX) {//当前缩放比例在一级缩放和二级缩放比例之间
                        //二级放大
                        postDelayed(new AutoScaleTask(SCALE_MAX, x, y), 10);
                    } else if (scale == SCALE_MAX) {//当前缩放比例等于二级缩放比例
                        //缩小至自适应view比例
                        postDelayed(new AutoScaleTask(SCALE_ADAPTIVE, x, y), 10);
                    } else {
                        isAutoScaling = false;
                    }
                }
                return super.onDoubleTap(e);
            }
        };
        return new GestureDetector(context, listner);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    ……
        if (mGestureDetector != null) {
            //绑定手势探测器,由其处理touch事件
            mGestureDetector.onTouchEvent(event);
        }
        return true;
    }
    
    private class AutoScaleTask implements Runnable {
    ……
        @Override
        public void run() {
         ……
            if (tmpScale > 1 && scale < targetScale || scale > targetScale && tmpScale < 1) {
                ……
            } else {//缩放的略微过头了,需要强制设定为目标缩放值
                ……
                isAutoScaling = false;
            }
        }
    }
    
              终于进入最后一个功能实现:手势移动。这里依然借助系统给我们算好的拖拽临界值ScaledTouchSlop决定是否拖动图片。重写onTouchEvent()处理touch事件判断用户拖动(ActionMove)值是否达到临界值,是则从手势触点(Point)的中心点(因为可能不止一个手指在拖动,需要求中心点)出发移动图片:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    ……
        //不在自动缩放中才可以拖动图片(这个判断可有可无,根据需求来)
        if (!isAutoScaling) {
            //绑定touch事件,处理移动图片逻辑
            moveByTouchEvent(event);
        }
        return true;
    }
    
    /**
     * 通过Touch事件移动图片
     *
     * @param event
     */
    private void moveByTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE://手势移动
                RectF rect = getMatrixRect();
                if (rect.width() <= getWidth() && rect.height() <= getHeight()) {
                    //图片宽高小于等于View宽高,即图片可以完全显示于屏幕中,那就没必要拖动了
                    return;
                }
                //计算多个触点的中心坐标
                int x = 0;
                int y = 0;
                int pointerCount = event.getPointerCount();//获取触点数(手指数)
                for (int i = 0; i < pointerCount; i++) {
                    x += event.getX(i);
                    y += event.getY(i);
                }
                //得到最终的中心坐标
                x /= pointerCount;
                y /= pointerCount;
    
                //如果触点数(手指数)发生变化,需要重置上一次中心坐标和数量的参考值
                if (mLastPointCount != pointerCount) {
                    mLastX = x;
                    mLastY = y;
                    mLastPointCount = pointerCount;
                }
                int deltaX = x - mLastX;//X方向的位移
                int deltaY = y - mLastY;//Y方向的位移
                //如果可以拖拽
                if (isCanDrag(deltaX, deltaY)) {
    
                    //图片宽小于等于view宽,则X方向不需要移动
                    if (rect.width() <= getWidth()) {
                        deltaX = 0;
                    }
                    //图片高小于等于view高,则Y方向不需要移动
                    if (rect.height() <= getHeight()) {
                        deltaY = 0;
                    }
                    //完成缩放
                    mScaleMatrix.postTranslate(deltaX, deltaY);
                    checkBoderAndCenter();
                    setImageMatrix(mScaleMatrix);
                }
                //交换中心坐标值,作为下次移动事件的参考值
                mLastX = x;
                mLastY = y;
                break;
            case MotionEvent.ACTION_CANCEL://取消
            case MotionEvent.ACTION_UP://释放
                mLastPointCount = 0;//触点数置零,便于下次判断是否重置mLastX和mLastY
                break;
        }
    }
    
    //上一次触点中心坐标
    int mLastX;//上一次拖动图片的触点数(手指数)
    int mLastY;
    //上一次拖动图片的触点数(手指数)
    int mLastPointCount;
    
    /**
     * 是否可以移动图片
     *
     * @param deltaX
     * @param deltaY
     */
    private boolean isCanDrag(int deltaX, int deltaY) {
        return Math.sqrt(deltaX * deltaX + deltaY * deltaY) >= mTouchSlop;
    }

              好了,几经周折终于把查看大图的功能搞定了,这里就不贴效果图了,下一篇再见!


    
    

    展开全文
  • tensorflow:大于阈值置1,小于置0

    千次阅读 2020-04-17 22:39:53
    看了 UeFan写的tensorflow tf.where使用方法,大于某个值为1,小于为0文章,依然有些模糊,自己结合实际注解了一下。 a=tf.random.uniform([2,2]) #随机生成2*2矩阵a one = tf.ones_like(a) #生成与a大小一致的值...
  • 使用TL494制作0-60V,0-20A,BUCK恒流恒压可调电源。 经过测试,电源效率在95%以上 最高输入电压可在MOS管耐压允许的情况下在100V以上 完整详细电路请下载。 PCB成品图片: 正面: 反面: 各控制端子: 原理...
  • 、三三通的不常用 之前检索六步换向的方式都为无刷电机如何换向,也未有文献提到三三通方式。上午检索三三通方式,文献也极少,其应用多为BLDCM高频链驱动器。 查看原因: 1. 三三通可以提高绕组利用率,...
  • 题目: Given an integer n, return the number of trailing zeroes in n!. Note: Your solution should be in logarithmic... 中有多少个后导0. 我们来找一下规律,考虑n!的质数因子。后缀0,只有可能是质因子2
  • 阿里大于短信验证码简单实现

    千次阅读 2017-11-08 11:11:30
    (阿里大于申请) 2、短信签名和短信模板(需要短信签名的名称和短信模板的模板code) 下面是阿里大于下载的demo,里面你很详细的说明了需要依赖的jar包。由于maven中没有相关jar包,需要我们先下载jar包并导入到...
  • NPN三极管通数据总结

    千次阅读 2017-04-25 10:49:40
    放大区:Ube>0.5开始,注意并不是要大于0.7V,0.7V是二极管的通电压,在放大区里,Ube一般是大于0.5V,小于0.65V,此时Ic是Ib的线性放大倍数。 饱和区:随着Ube大于0.65以上,Ic基本上不会再增大,此时Uce会很快...
  • 率测试仪器及原理

    千次阅读 2019-11-15 10:29:27
    率它的物理意义是表示磁介质中磁感应...通常使用的是磁介质的相对磁率μr,其定义为磁率μ与真空磁率μ0之比,即μr=μ/μ0 ,相对磁率μr与磁化率χ的关系是:μr=1+χ 磁率μ,相对磁率μr和磁...
  • 然后在应用管理-》应用列列表栏创建应用,应用名为短信的最前面中括号中内容,大于官方会给你提供个appKey和AppSecret代码中会用到。 2.创建好应用后就需要在配置管理中添加对应的模板,企业用户默认会有...
  • 针对特征P>3的域上的有限维奇Hamiltonian李超代数HO的偶部到广义Witt李超代数w的奇部的非负Z-齐次子的问题,利用H0偶部的生成元集,...则此子为结论,然后得出了HO的偶部到W的奇部的Z-次数大于等于子.
  • http://blog.csdn.net/xiaofengsheng/article/details/6023368 ...  1. 一阶差分: ...2. 二阶偏数的推导和近似:   3. 上式以点(i+1,j)为中心,用i代换i+1可得以(i,
  • 本文内容大致翻译自Machine Learning for Beginners: An ...简单解释神经网络如何工作,并且从开始使用Python实现个神经网络。 神经网络可能并没有你想象的那么复杂。虽然“神经网络”这个词经常被用...
  • php读取excel 列数大于Z时读取不到

    千次阅读 2019-01-01 20:19:13
    之前测试一直没有问题,但是到线上上传的时候却出了问题,开始百思不得其解,后来一点一点打断点调试的时候发现了问题,循环的时候AA++的时候就没有办法识别,结果总是个0,然后开始上网找各种解决办法 ...
  • NMOS和PMOS通电流 走向

    千次阅读 2021-01-12 18:32:26
    我们常用的是NMOS,因为其通电阻小,且容易制造。在MOS管原理图上可以看到,漏极和源极之间有个寄生二极管。这个叫体二极管,在驱动感性负载(如马达),这个二极管很重要。顺便说句,体二极管只在单个的MOS管...
  • MOSFET 通条件

    千次阅读 2019-04-13 21:40:39
    MOSFET管是FET的种,可以被制造为增强型或者耗尽型,P沟道或N沟道共四种类型,但实际应用的只有增强型的N沟道MOS管和增强型的P沟道MOS管。实际应用中,NMOS居多。 如何分辨三个极?D极单独位于一边,而G极是第4...
  • 金属-氧化层半导体场效晶体管,简称金氧半场效晶体管是种可以广泛使用在模拟电路与数字电路的场效晶体管。MOSFET依照其“通道”的极性不同,可分为“N型”与“P型”的MOSFET,通常又称为NMOSFET与PMOSFET,其他...
  • nmos和pmos通条件

    千次阅读 2021-01-12 18:14:53
    nmos和pmos通条件-详解nmos和pmos通电路图及区别-KIA MOS管 NMOS与PMOS有什么区别 什么是nmos NMOS英文全称为N-Metal-Oxide-Semiconductor。 意思为N型金属-氧化物-半导体,而拥有这种结构的晶体管我们称...
  • Python 基于sympy模块求极值 导数 偏

    千次阅读 2019-11-20 21:22:04
    sympy简介:sympy是个Python的...1、求极限、求导、求偏以及带值求导 在这里插入代码import sympy #求极限 #设置符号变量Symbol只能创建个变量 symbols 可次定义多个变量 x1,x2,x3,x4=sympy.symbols('x1,x...
  • 参数为传过来的事实表名称,用于构建查询sql参数二为指定导出文件格式参数三为数据集名称,用于定义文件名#!/bin/bashexport NLS_LANG="AMERICAN_AMERICA.AL32UTF8"factName=$1format=$2cubeName=$3OUT_...
  • 在 C 语言中 if 语句表示判断个条件是否成立,例如用户输入个数,判断这个数是否为指定的个数: int a=0; scanf("%d",&a); if(a==3){ printf("用户输入的是 3 "); } 以上代码首先创建了个变量 a 存储的值...
  • [toc] 凸函数 若函数 f 的定义域 domf 为凸集, 且满足 则有: ...若 f 一阶可微, 则函数 f...若 f 是一元函数, 上式表示二阶导大于等于 0 若 f 是多元函数, 上式表示二阶导 HEssian 矩阵半正定. 凸函数举例 ...
  • 开关三极管的通和截止条件

    万次阅读 多人点赞 2018-06-01 22:15:54
    转自:...在我们板子上的 LED 小灯部分,就有这个三极管的应用了,图 3-5 的 LED 电路中的 Q16就是个 PNP 型的三极管。图 3-5 LED 电路三极管的初步认识三极管是...
  • 将DBF数据文件成excel文件的问题

    千次阅读 2017-07-20 08:12:47
    用 copy to EXCEL表名 type xl5 只能导出16383条记录,超过此数的用以下方法导出: 方法: 如果你的数据中都是普通的数值和字符串类型,直接用Excel打开表,然后“另存为”个Excel...方法二:用代码 && DbfToE
  • 线束通测试仪使用说明书

    千次阅读 2020-03-04 10:21:36
     线束通测试仪的主要功能是利用与样品线束比对的方式检测出线束中可能存在的开路、短路和错位几种错误,测试结果会以显示屏、指示灯、蜂鸣器进行提示,还可以利用屏幕信息进一步定位到具体的出错线路。...
  • 由光耦的特性可知,其主要的参数有CTR,If,IC以及开关延迟...由于有时光耦的的通并不一定是完全饱和的,即光耦是电流驱动的,光耦输出支路的电压和电流受限于具体的光耦电流驱动能力,光耦饱和通时的VCE(一般为0.
  • 开关二极管的通和截止条件

    千次阅读 2018-02-23 16:20:25
    三极管在我们数字电路和模拟电路中都有大量的应用,在我们开发板上也用了多个...在我们板子上的 LED 小灯部分,就有这个三极管的应用了,图 3-5 的 LED 电路中的 Q16就是个 PNP 型的三极管。 图 3-5 LED ...
  • 北邮2019计下 链表二 A. 实验11_9_链表归并

    千次阅读 多人点赞 2019-03-21 19:32:41
    这题有些奇怪,前8组很顺利,第9组数据死活过不了,提示运行时错误。找老师拿来了测试数据,不论是手动输入、freopen重定向还是...设计lowerBound函数,其用途是,对于个给定的数key,找出链表A中不大于k...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,672
精华内容 13,868
关键字:

一导大于零