Android实现支持缩放平移图片

本文主要用到了以下知识点

  1. Matrix
  2. GestureDetector 能够捕捉到长按、双击
  3. ScaleGestureDetector 用于检测缩放的手势

自由的缩放

需求:当图片加载时,将图片在屏幕中居中;图片宽或高大于屏幕的,缩小至屏幕大小;自由对图片进行方法或缩小;

package com.zhy.view;  import android.content.Context;  
import android.graphics.Matrix;  
import android.graphics.drawable.Drawable;  
import android.util.AttributeSet;  
import android.util.Log;  
import android.view.MotionEvent;  
import android.view.ScaleGestureDetector;  
import android.view.ScaleGestureDetector.OnScaleGestureListener;  
import android.view.View;  
import android.view.View.OnTouchListener;  
import android.view.ViewTreeObserver;  
import android.widget.ImageView;  public class ZoomImageView extends ImageView implements OnScaleGestureListener,  OnTouchListener, ViewTreeObserver.OnGlobalLayoutListener  {  private static final String TAG = ZoomImageView.class.getSimpleName();  public static final float SCALE_MAX = 4.0f;  /** * 初始化时的缩放比例,如果图片宽或高大于屏幕,此值将小于0 */  private float initScale = 1.0f;  /** * 用于存放矩阵的9个值 */  private final float[] matrixValues = new float[9];  private boolean once = true;  /** * 缩放的手势检测 */  private ScaleGestureDetector mScaleGestureDetector = null;  private final Matrix mScaleMatrix = new Matrix();  public ZoomImageView(Context context)  {  this(context, null);  }  public ZoomImageView(Context context, AttributeSet attrs)  {  super(context, attrs);  super.setScaleType(ScaleType.MATRIX);  mScaleGestureDetector = new ScaleGestureDetector(context, this);  this.setOnTouchListener(this);  }  @Override  public boolean onScale(ScaleGestureDetector detector)  {  float scale = getScale();  float scaleFactor = detector.getScaleFactor();  if (getDrawable() == null)  return true;  /** * 缩放的范围控制 */  if ((scale < SCALE_MAX && scaleFactor > 1.0f)  || (scale > initScale && scaleFactor < 1.0f))  {  /** * 最大值最小值判断 */  if (scaleFactor * scale < initScale)  {  scaleFactor = initScale / scale;  }  if (scaleFactor * scale > SCALE_MAX)  {  scaleFactor = SCALE_MAX / scale;  }  /** * 设置缩放比例 */  mScaleMatrix.postScale(scaleFactor, scaleFactor, getWidth() / 2,  getHeight() / 2);  setImageMatrix(mScaleMatrix);  }  return true;  }  @Override  public boolean onScaleBegin(ScaleGestureDetector detector)  {  return true;  }  @Override  public void onScaleEnd(ScaleGestureDetector detector)  {  }  @Override  public boolean onTouch(View v, MotionEvent event)  {  return mScaleGestureDetector.onTouchEvent(event);  }  /** * 获得当前的缩放比例 *  * @return */  public final float getScale()  {  mScaleMatrix.getValues(matrixValues);  return matrixValues[Matrix.MSCALE_X];  }  @Override  protected void onAttachedToWindow()  {  super.onAttachedToWindow();  getViewTreeObserver().addOnGlobalLayoutListener(this);  }  @SuppressWarnings("deprecation")  @Override  protected void onDetachedFromWindow()  {  super.onDetachedFromWindow();  getViewTreeObserver().removeGlobalOnLayoutListener(this);  }  @Override  public void onGlobalLayout()  {  if (once)  {  Drawable d = getDrawable();  if (d == null)  return;  Log.e(TAG, d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());  int width = getWidth();  int height = getHeight();  // 拿到图片的宽和高  int dw = d.getIntrinsicWidth();  int dh = d.getIntrinsicHeight();  float scale = 1.0f;  // 如果图片的宽或者高大于屏幕,则缩放至屏幕的宽或者高  if (dw > width && dh <= height)  {  scale = width * 1.0f / dw;  }  if (dh > height && dw <= width)  {  scale = height * 1.0f / dh;  }  // 如果宽和高都大于屏幕,则让其按按比例适应屏幕大小  if (dw > width && dh > height)  {  scale = Math.min(dw * 1.0f / width, dh * 1.0f / height);  }  initScale = scale;  // 图片移动至屏幕中心  mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);  mScaleMatrix  .postScale(scale, scale, getWidth() / 2, getHeight() / 2);  setImageMatrix(mScaleMatrix);  once = false;  }  }  }  

1、我们在onGlobalLayout的回调中,根据图片的宽和高以及屏幕的宽和高,对图片进行缩放以及移动至屏幕的中心。如果图片很小,那就正常显示,不放大了~
2、我们让OnTouchListener的MotionEvent交给ScaleGestureDetector进行处理

@Override  public boolean onTouch(View v, MotionEvent event)  {  return mScaleGestureDetector.onTouchEvent(event);  }  

3、在onScale的回调中对图片进行缩放的控制,首先进行缩放范围的判断,然后设置mScaleMatrix的scale值
现在的效果:

存在问题:

1、缩放的中心点,我们设置是固定的,屏幕中间
2、放大后,无法移动~

设置缩放中心

1、单纯的设置缩放中心
仅仅是设置中心很简单,直接修改下中心点 :

/** * 设置缩放比例 */  mScaleMatrix.postScale(scaleFactor, scaleFactor,  detector.getFocusX(), detector.getFocusX());  setImageMatrix(mScaleMatrix);  

但是,随意的中心点放大、缩小,会导致图片的位置的变化,最终导致,图片宽高大于屏幕时,图片与屏幕间出现白边;图片小于屏幕,但是不居中。

2、控制缩放时图片显示的范围
所以我们在缩放的时候需要手动控制下范围:

/** * 在缩放时,进行图片显示范围的控制 */  private void checkBorderAndCenterWhenScale()  {  RectF rect = getMatrixRectF();  float deltaX = 0;  float deltaY = 0;  int width = getWidth();  int height = getHeight();  // 如果宽或高大于屏幕,则控制范围  if (rect.width() >= width)  {  if (rect.left > 0)  {  deltaX = -rect.left;  }  if (rect.right < width)  {  deltaX = width - rect.right;  }  }  if (rect.height() >= height)  {  if (rect.top > 0)  {  deltaY = -rect.top;  }  if (rect.bottom < height)  {  deltaY = height - rect.bottom;  }  }  // 如果宽或高小于屏幕,则让其居中  if (rect.width() < width)  {  deltaX = width * 0.5f - rect.right + 0.5f * rect.width();  }  if (rect.height() < height)  {  deltaY = height * 0.5f - rect.bottom + 0.5f * rect.height();  }  Log.e(TAG, "deltaX = " + deltaX + " , deltaY = " + deltaY);  mScaleMatrix.postTranslate(deltaX, deltaY);  }  /** * 根据当前图片的Matrix获得图片的范围 *  * @return */  private RectF getMatrixRectF()  {  Matrix matrix = mScaleMatrix;  RectF rect = new RectF();  Drawable d = getDrawable();  if (null != d)  {  rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());  matrix.mapRect(rect);  }  return rect;  }  

自由的进行移动

@Override  public boolean onTouch(View v, MotionEvent event)  {  mScaleGestureDetector.onTouchEvent(event);  float x = 0, y = 0;  // 拿到触摸点的个数  final int pointerCount = event.getPointerCount();  // 得到多个触摸点的x与y均值  for (int i = 0; i < pointerCount; i++)  {  x += event.getX(i);  y += event.getY(i);  }  x = x / pointerCount;  y = y / pointerCount;  /** * 每当触摸点发生变化时,重置mLasX , mLastY  */  if (pointerCount != lastPointerCount)  {  isCanDrag = false;  mLastX = x;  mLastY = y;  }  lastPointerCount = pointerCount;  switch (event.getAction())  {  case MotionEvent.ACTION_MOVE:  Log.e(TAG, "ACTION_MOVE");  float dx = x - mLastX;  float dy = y - mLastY;  if (!isCanDrag)  {  isCanDrag = isCanDrag(dx, dy);  }  if (isCanDrag)  {  RectF rectF = getMatrixRectF();  if (getDrawable() != null)  {  isCheckLeftAndRight = isCheckTopAndBottom = true;  // 如果宽度小于屏幕宽度,则禁止左右移动  if (rectF.width() < getWidth())  {  dx = 0;  isCheckLeftAndRight = false;  }  // 如果高度小雨屏幕高度,则禁止上下移动  if (rectF.height() < getHeight())  {  dy = 0;  isCheckTopAndBottom = false;  }  mScaleMatrix.postTranslate(dx, dy);  checkMatrixBounds();  setImageMatrix(mScaleMatrix);  }  }  mLastX = x;  mLastY = y;  break;  case MotionEvent.ACTION_UP:  case MotionEvent.ACTION_CANCEL:  Log.e(TAG, "ACTION_UP");  lastPointerCount = 0;  break;  }  return true;  }  

首先我们拿到触摸点的数量,然后求出多个触摸点的平均值,设置给我们的mLastX , mLastY , 然后在移动的时候,得到dx ,dy 进行范围检查以后,调用mScaleMatrix.postTranslate进行设置偏移量,当然了,设置完成以后,还需要再次校验一下,不能把图片移动的与屏幕边界出现白边,校验完成后,调用setImageMatrix.

这里:需要注意一下,我们没有复写ACTION_DOWM,是因为,ACTION_DOWN在多点触控的情况下,只要有一个手指按下状态,其他手指按下不会再次触发ACTION_DOWN,但是多个手指以后,触摸点的平均值会发生很大变化,所以我们没有用到ACTION_DOWN。每当触摸点的数量变化,我们就会跟新当前的mLastX,mLastY.
下面是上面用到的两个私有方法,一个用于检查边界,一个用于判断是否是拖动的操作:

/** * 移动时,进行边界判断,主要判断宽或高大于屏幕的 */  private void checkMatrixBounds()  {  RectF rect = getMatrixRectF();  float deltaX = 0, deltaY = 0;  final float viewWidth = getWidth();  final float viewHeight = getHeight();  // 判断移动或缩放后,图片显示是否超出屏幕边界  if (rect.top > 0 && isCheckTopAndBottom)  {  deltaY = -rect.top;  }  if (rect.bottom < viewHeight && isCheckTopAndBottom)  {  deltaY = viewHeight - rect.bottom;  }  if (rect.left > 0 && isCheckLeftAndRight)  {  deltaX = -rect.left;  }  if (rect.right < viewWidth && isCheckLeftAndRight)  {  deltaX = viewWidth - rect.right;  }  mScaleMatrix.postTranslate(deltaX, deltaY);  }  /** * 是否是推动行为 *  * @param dx * @param dy * @return */  private boolean isCanDrag(float dx, float dy)  {  return Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;  }  

这样,我们就可以快乐的放大、缩小加移动了~~~

双击放大与缩小

谈到双击事件,我们的GestureDetector终于要登场了,这哥们可以捕获双击事件~~
1、GestureDetector的使用
因为GestureDetector设置监听器的话,方法一大串,而我们只需要onDoubleTap这个回调,所以我们准备使用它的一个内部类SimpleOnGestureListener,对接口的其他方法实现了空实现。
不过还有几个问题需要讨论下,才能开始我们的代码:

1、我们双击尺寸如何变化?
我是这样的,根据当前的缩放值,如果是小于2的,我们双击直接到变为原图的2倍;如果是2,4之间的,我们双击直接为原图的4倍;其他状态也就是4倍,双击后还原到最初的尺寸。
如果你觉得这样不合适,可以根据自己的爱好调整。

2、我们双击变化,需要一个动画~~比如我们上例的演示图,图片很大,全屏显示的时候initScale=0.5左后,如果双击后变为2,也就是瞬间大了四倍,没有一个过渡的效果的话,给用户的感觉会特别差。所以,我们准备使用postDelay执行一个Runnable,Runnable中再次根据的当然的缩放值继续执行。
首先我们在构造方法中,完成对GestureDetector的初始化,以及设置onDoubleTap监听

public ZoomImageView(Context context, AttributeSet attrs)  {  super(context, attrs);  mScaleGestureDetector = new ScaleGestureDetector(context, this);  mGestureDetector = new GestureDetector(context,  new SimpleOnGestureListener()  {  @Override  public boolean onDoubleTap(MotionEvent e)  {  if (isAutoScale == true)  return true;  float x = e.getX();  float y = e.getY();  Log.e("DoubleTap", getScale() + " , " + initScale);  if (getScale() < SCALE_MID)  {  ZoomImageView.this.postDelayed(  new AutoScaleRunnable(SCALE_MID, x, y), 16);  isAutoScale = true;  } else if (getScale() >= SCALE_MID  && getScale() < SCALE_MAX)  {  ZoomImageView.this.postDelayed(  new AutoScaleRunnable(SCALE_MAX, x, y), 16);  isAutoScale = true;  } else  {  ZoomImageView.this.postDelayed(  new AutoScaleRunnable(initScale, x, y), 16);  isAutoScale = true;  }  return true;  }  });  mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  super.setScaleType(ScaleType.MATRIX);  this.setOnTouchListener(this);  }  

1、当双击的时候,首先判断是否正在自动缩放,如果在,直接retrun ;
2、然后就进入了我们的if,如果当然是scale小于2,则通过view.发送一个Runnable进行执行;其他类似;
下面看我们的Runnable的代码:

/** * 自动缩放的任务 *  * @author zhy *  */  private class AutoScaleRunnable implements Runnable  {  static final float BIGGER = 1.07f;  static final float SMALLER = 0.93f;  private float mTargetScale;  private float tmpScale;  /** * 缩放的中心 */  private float x;  private float y;  /** * 传入目标缩放值,根据目标值与当前值,判断应该放大还是缩小 *  * @param targetScale */  public AutoScaleRunnable(float targetScale, float x, float y)  {  this.mTargetScale = targetScale;  this.x = x;  this.y = y;  if (getScale() < mTargetScale)  {  tmpScale = BIGGER;  } else  {  tmpScale = SMALLER;  }  }  @Override  public void run()  {  // 进行缩放  mScaleMatrix.postScale(tmpScale, tmpScale, x, y);  checkBorderAndCenterWhenScale();  setImageMatrix(mScaleMatrix);  final float currentScale = getScale();  //如果值在合法范围内,继续缩放  if (((tmpScale > 1f) && (currentScale < mTargetScale))  || ((tmpScale < 1f) && (mTargetScale < currentScale)))  {  ZoomImageView.this.postDelayed(this, 16);  } else//设置为目标的缩放比例  {  final float deltaScale = mTargetScale / currentScale;  mScaleMatrix.postScale(deltaScale, deltaScale, x, y);  checkBorderAndCenterWhenScale();  setImageMatrix(mScaleMatrix);  isAutoScale = false;  }  }  }  

代码写完了,我们依然需要把我们的event传给它,依然是在onTouch方法:

@Override  public boolean onTouch(View v, MotionEvent event)  {  if (mGestureDetector.onTouchEvent(event))  return true;  

与ViewPager一起使用时的事件冲突问题

现在我们迅速的想一想,记得之前学习过事件分发机制,我们的ZoomImageView在ViewPager中,如果我们不想被拦截,那么如何做呢?
首先不想被拦截的条件是:我们的宽或高大于屏幕宽或高时,因为此时可以移动,我们不想被拦截。接下来,不想被拦截:
getParent().requestDisallowInterceptTouchEvent(true);
一行代码足以

switch (event.getAction())  {  case MotionEvent.ACTION_DOWN:  if (rectF.width() > getWidth() || rectF.height() > getHeight())  {  getParent().requestDisallowInterceptTouchEvent(true);  }  break;  case MotionEvent.ACTION_MOVE:  if (rectF.width() > getWidth() || rectF.height() > getHeight())  {  getParent().requestDisallowInterceptTouchEvent(true);  }  

requestDisallowInterceptTouchEvent

ViewPager来实现左右滑动切换tab,如果tab的某一项中嵌入了水平可滑动的View就会让你有些不爽,比如想滑动tab项中的可水平滑动的控件,却导致tab切换。

因为Android事件机制是从父View传向子View的,可以去检测你当前子View是不是在有可滑动控件等,决定事件是否拦截,但是这个麻烦,而且并不能解决所有的问题(必须检测触摸点是否在这个控件上面),其实有比较简单的方法,在你嵌套的控件中注入ViewPager实例(调用控件的getParent()方法),然后在onTouchEvent,onInterceptTouchEvent,dispatchTouchEvent里面告诉父View,也就是ViewPager不要拦截该控件上的触摸事件。

参考链接

requestDisallowInterceptTouchEvent - 喜糖 - 博客园

postDelayed方法

这是一种可以创建多线程消息的函数  
使用方法:  
1,首先创建一个Handler对象  
Handler handler=new Handler();  
2,然后创建一个Runnable对象  
Runnable runnable=new Runnable(){  @Override  public void run() {  // TODO Auto-generated method stub  //要做的事情,这里再次调用此Runnable对象,以实现每两秒实现一次的定时器操作  handler.postDelayed(this, 2000);  }   
};  
3,使用PostDelayed方法,两秒后调用此Runnable对象  
handler.postDelayed(runnable, 2000);  
实际上也就实现了一个2s的一个定时器  
4,如果想要关闭此定时器,可以这样操作  
handler.removeCallbacks(runnable);  当然,你也可以做一个闹钟提醒延时的函数试试,比如,先用MediaPlayer播放闹钟声音,  
如果不想起,被停止播放之后,下次就5分钟后再播放,再被停止的话,下次就4分钟后播放,  
………………  
只要更改延时的时间就可以实现了,用一个static对象的话会比较容易操作。  全手打原创哦,百度能告诉你的我就不告诉你了。 

参考链接

关于 android 中 postDelayed方法的讲解 - - ITeye技术网站

源代码

放大功能

单图版源码点击下载

ViewPager版源码下载

本文主要参考

Android 手势检测实战 打造支持缩放平移的图片预览效果(上) - Hongyang - 博客频道 - CSDN.NET

Android 手势检测实战 打造支持缩放平移的图片预览效果(下) - Hongyang - 博客频道 - CSDN.NET

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494115.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

放麦子

题意&#xff1a; 国际象棋&#xff0c;一共64个方格&#xff0c;第一个格子里放一粒麦子&#xff0c;第二个放2粒&#xff0c;第三个放4粒&#xff0c;第四个放8粒。。。。。&#xff08;后面的数字是前面的两倍&#xff09; 求放满64个格子&#xff0c;一共需要多少粒麦子。 …

Material Design风格登录注册

本文实现了以下功能 完整的代码和样例托管在Github当接口锁定时&#xff0c;防止后退按钮显示在登录Activity 上。自定义 ProgressDialog来显示加载的状态。符合材料设计规范。悬浮标签&#xff08;floating labels&#xff09;&#xff08;来自设计支持库&#xff09;用户表单…

英特尔反驳质疑:芯片供应充足、10nm量产没问题

来源&#xff1a;华尔街见闻摘要&#xff1a;英特尔称2018年会将资本支出增加10亿美元&#xff0c;至总额创纪录的150亿美元&#xff1b;CEO称&#xff0c;个人电脑需求意外回升&#xff0c;但有足够供应满足市场&#xff0c;有望达成全年营收目标&#xff0c;股价涨近4%。竞争…

RecyclerView拖拽排序和滑动删除实现

效果图 如何实现 那么是如何实现的呢&#xff1f;主要就要使用到ItemTouchHelper &#xff0c;ItemTouchHelper 一个帮助开发人员处理拖拽和滑动删除的实现类&#xff0c;它能够让你非常容易实现侧滑删除、拖拽的功能。 实现的代码非常简单我们只需要两步&#xff1a; 实例化…

马斯克刚刚宣布辞去特斯拉董事会职务,仍然担任CEO

来源&#xff1a;大数据文摘编译&#xff1a;蒋宝尚据悉&#xff0c;当地时间周六&#xff0c;马斯克辞去特斯拉董事会主席一职&#xff0c;并且支付2000万美元罚款。以表示对美国证券交易委员会(SEC)指控的回应。SEC的指控来源于马斯克8月7日的一篇推文。推文中&#xff0c;他…

JavaScript 实现 GriwView 单列全选

在 GridView 里有一系列的 Checkbox &#xff0c;要实现对其全选或全不选。开始在网上找了&#xff0c;但是参考的代码会全选 GridView 里所有的 Checkbox &#xff0c;而我要的是单列全选。如图&#xff1a; 审核和权限是要分开的。 我自己写了 JavaScript 代码&#xff0c;贴…

自然语言处理(NLP)前沿进展报告

来源&#xff1a;专知摘要&#xff1a;2018年9 月 9 日-14 日&#xff0c;DeepMind主办的Deep Learning Indaba 2018 大会在南非斯泰伦博斯举行。会上&#xff0c;斯坦陵布什大学Herman Kamper和AYLIEN的Sebastian Ruder等专家做了《自然语言处理前言进展》的报告。报告首先探讨…

Android下利用Bitmap切割图片

在自己自定义的一个组件中由于需要用图片显示数字编号&#xff0c;而当前图片就只有一张&#xff0c;上面有0-9是个数字&#xff0c;于是不得不考虑将其中一个个的数字切割下来&#xff0c;需要显示什么数字&#xff0c;只需要组合一下就好了。 下面是程序的关键代码&#xff…

两种不同的人工智能观:工程观点和科学观点

来源&#xff1a;人机与认知实验室作者按&#xff1a;人工智能是作为工程还是科学&#xff0c;这个问题是一个很严肃的问题&#xff0c;如果从工程技术角度来看人工智能&#xff0c;那么认知科学尤其是认知心理学、神经生理学对人类这样的生物智能的原理性认识&#xff0c;就不…

BaseActivity与BaseFragment的封装

这篇博客主要是从BaseActivity与BaseFragment的封装开始&#xff0c;总结我们在实战开发中关于Fragment的注意事项以及心得体会。 先看以下效果图&#xff1a; 这里模拟的是用户登录模块&#xff0c;你可能会说&#xff0c;很普通的效果嘛&#xff0c;这有啥。嘿嘿&#xff0c…

学界 | 史上最强GAN图像生成器,Inception分数提高两倍

来源&#xff1a;Openreview,机器之心摘要&#xff1a;ICLR 2019 大会即将在明年 5 月 6 日于美国举行&#xff0c;9 月 27 日论文提交截止时间已过。本次大会共接收到了 1591 篇论文的投稿&#xff0c;数量相较今年的 1000 篇提升了近 60%。在双盲评审时&#xff0c;人们可以在…

一图理解腾讯本次组织结构重大变革的方向和目的

作者&#xff1a;刘锋 互联网进化论作者 计算机博士2018年9月30日&#xff0c;腾讯宣布公司架构调整&#xff0c;在原有七个事业群的基础上进行重组整合&#xff0c;形成新的6个事业群&#xff0c;在本次调整中&#xff0c;腾讯新成立了云与智慧产业事业群&#xff08;CSIG&…

Android实现边缘凹凸的View

转载 最近做项目的时候遇到一个卡劵的效果&#xff0c;由于自己觉得用图片来做的话可以会出现适配效果不好&#xff0c;再加上自己自定义view方面的知识比较薄弱&#xff0c;所以想试试用自定义View来实现。但是由于自己知识点薄弱&#xff0c;一开始居然想着用画矩形来设置边…

【报告解读】126个国家、29个行业、36位高管认为AI的未来这么走

来源&#xff1a;网易智能人工智能&#xff08;AI&#xff09;已经使早期采用它的制造商能够更好地协调分析、商业智能(BI)、移动性和实时监控&#xff0c;以实现更快的营收增长&#xff0c;并比同行更快地成长壮大。如今&#xff0c;最顶级的18%的AI采用者将超过70%的精力投入…

自定义view实现水波纹效果

水波纹效果&#xff1a; 1.标准正余弦水波纹&#xff1b; 2.非标准圆形液柱水波纹&#xff1b; 虽说都是水波纹&#xff0c;但两者在实现上差异是比较大的&#xff0c;一个通过正余弦函数模拟水波纹效果&#xff0c;另外一个会运用到图像的混合模式&#xff08;PorterDuffXf…

“人机耦合”变成“人机大战” AI同传离成熟还有多远

来源&#xff1a;科学网9月21日&#xff0c;一篇指责科大讯飞“AI同传造假”的文章引发了社会广泛关注&#xff0c;文中知乎用户、同传译员Bell Wang表示&#xff0c;在日前举行的2018创新与新兴产业发展国际会议上&#xff0c;科大讯飞在现场和直播中展示的“AI同传”&#xf…

高中分类讨论题1

转载于:https://www.cnblogs.com/zjyyhs/archive/2013/05/23/3094220.html

Android拼图游戏

效果如下 游戏的设计 首先我们分析下如何设计这款游戏&#xff1a; 1、我们需要一个容器&#xff0c;可以放这些图片的块块&#xff0c;为了方便&#xff0c;我们准备使用RelativeLayout配合addRule实现 2、每个图片的块块&#xff0c;我们准备使用ImageView 3、点击交换&a…

亚马逊:从零售商向科技公司的质变

报告来源&#xff1a;国泰君安&#xff08;訾猛&#xff09;亚马逊以技术为核心驱动力&#xff0c;实现从电商向科技公司的跨越&#xff0c;形成电商、物流、AWS、新零售协同发展的完整生态圈。亚马逊从1995年开始为用户提供线上商品&#xff0c;从一家网上书店发展成全品类电商…

使用HTML5的Canvas画布来剪裁用户头像

日期&#xff1a;2013-5-23 来源&#xff1a;GBin1.com 本文来自极客标签社区用户webgeek的一个在线HTML5web开发小技巧&#xff0c;帮助你使用html5的画布功能来切割用户上传的大头照。 在线调试 例如需要剪裁的图片如下&#xff1a; 用来处理大头照的JS代码如下&#xff1a;…