- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
所以,我有用于 TicTacToe 游戏的 ScrollView、HorizantalScrollView 和 BoardView。
当用户缩放时,虽然我通过 ScalegestureDetector 将缩放比例重新绘制到单元格类别中,但缩放捏点分配在屏幕左侧的顶部,而不是捏点的中心,我如何将其分配到中心?
这是我在 github 中的项目:https://github.com/boyfox/TestTicTac.git
项目使用com.android.support:appcompat-v7
谁有办法解决这个问题?
最佳答案
我认为您将希望转向更接近 Android Dragging and Scaling examples 的实现(以及类似的问题 here)。
这是您需要的开始。您可以像以前一样平移 View ,现在可以在捏合手势的中心缩放 View 。它是您的基本 BoardView,具有根据 here 的点击绘制点的逻辑.绘制自定义 X 和 O 图标而不是圆应该很容易。
BoardView.java
public class BoardView extends View {
private static final int JUST_SCALED_DURATION = 100;
private static final int MAX_TOUCH_DURATION = 1000;
private static final int MAX_TOUCH_DISTANCE = 10;
private boolean stayedWithinTouchDistance;
private float firstTouchX, firstTouchY;
private long firstTouchTime, lastScaleTime;
private float posX, posY, lastTouchX, lastTouchY;
private ScaleGestureDetector scaleDetector;
private float minScaleFactor = 0.1f;
private float maxScaleFactor = 5.0f;
private float scaleFactor = 1.0f;
private float cellSize = 50.0f;
private int numCells = 50;
private ArrayList<Point> points;
private Paint linePaint, pointPaint;
public BoardView(Context context) {
this(context, null, 0);
}
public BoardView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BoardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
points = new ArrayList<>();
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setColor(-65536);
linePaint.setStrokeWidth(1.0f);
pointPaint = new Paint();
pointPaint.setAntiAlias(true);
pointPaint.setColor(-65536);
pointPaint.setStrokeWidth(1.0f);
posX = linePaint.getStrokeWidth();
posY = linePaint.getStrokeWidth();
scaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private static float distancePx(float x1, float y1, float x2, float y2) {
float dx = x1 - x2;
float dy = y1 - y2;
return (float) Math.sqrt(dx * dx + dy * dy);
}
private float distanceDp(float distancePx) {
return distancePx / getResources().getDisplayMetrics().density;
}
private Point coerceToGrid(Point point) {
point.x = (int) ((((int) (point.x / cellSize)) * cellSize) + (cellSize / 2));
point.y = (int) ((((int) (point.y / cellSize)) * cellSize) + (cellSize / 2));
return point;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
scaleDetector.onTouchEvent(event);
final int action = MotionEventCompat.getActionMasked(event);
if (action == MotionEvent.ACTION_DOWN) {
stayedWithinTouchDistance = true;
firstTouchX = lastTouchX = event.getRawX();
firstTouchY = lastTouchY = event.getRawY();
firstTouchTime = System.currentTimeMillis();
} else if (action == MotionEvent.ACTION_MOVE) {
float thisTouchX = event.getRawX();
float thisTouchY = event.getRawY();
boolean justScaled = System.currentTimeMillis() - lastScaleTime < JUST_SCALED_DURATION;
float distancePx = distancePx(firstTouchX, firstTouchY, thisTouchX, thisTouchY);
stayedWithinTouchDistance = stayedWithinTouchDistance &&
distanceDp(distancePx) < MAX_TOUCH_DISTANCE;
if (!stayedWithinTouchDistance && !scaleDetector.isInProgress() && !justScaled) {
posX += thisTouchX - lastTouchX;
posY += thisTouchY - lastTouchY;
invalidate();
}
lastTouchX = thisTouchX;
lastTouchY = thisTouchY;
} else if (action == MotionEvent.ACTION_UP) {
long touchDuration = System.currentTimeMillis() - firstTouchTime;
if (touchDuration < MAX_TOUCH_DURATION && stayedWithinTouchDistance) {
int[] location = {0, 0};
getLocationOnScreen(location);
float x = ((lastTouchX - posX - location[0]) / scaleFactor);
float y = ((lastTouchY - posY - location[1]) / scaleFactor);
points.add(coerceToGrid(new Point((int) x, (int) y)));
invalidate();
}
}
return true;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
lastScaleTime = System.currentTimeMillis();
float scale = detector.getScaleFactor();
scaleFactor = Math.max(minScaleFactor, Math.min(scaleFactor * scale, maxScaleFactor));
if (scaleFactor > minScaleFactor && scaleFactor < maxScaleFactor) {
float centerX = detector.getFocusX();
float centerY = detector.getFocusY();
float diffX = centerX - posX;
float diffY = centerY - posY;
diffX = diffX * scale - diffX;
diffY = diffY * scale - diffY;
posX -= diffX;
posY -= diffY;
invalidate();
return true;
}
return false;
}
}
private float getScaledCellSize() {
return scaleFactor * cellSize;
}
private float getScaledBoardSize() {
return numCells * getScaledCellSize();
}
private void drawBoard(Canvas canvas) {
for (int i = 0; i <= numCells; i++) {
float total = getScaledBoardSize();
float offset = getScaledCellSize() * i;
canvas.drawLine(offset, 0, offset, total, linePaint);
canvas.drawLine(0, offset, total, offset, linePaint);
}
}
private void drawPoints(Canvas canvas) {
for (Point point : points) {
float x = point.x * scaleFactor;
float y = point.y * scaleFactor;
float r = getScaledCellSize() / 4;
canvas.drawCircle(x, y, r, pointPaint);
}
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
float total = getScaledBoardSize();
float edge = linePaint.getStrokeWidth();
posX = Math.max(Math.min(edge, getWidth() - total - edge), Math.min(edge, posX));
posY = Math.max(Math.min(edge, getHeight() - total - edge), Math.min(edge, posY));
canvas.save();
canvas.translate(posX, posY);
drawBoard(canvas);
drawPoints(canvas);
canvas.restore();
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.client.BoardView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
关于安卓 : Zoom by center pinch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30890868/
我在学习如何缩放方面经历了一段痛苦的时光。为了学习,我一直在尝试制作树状图缩放。我正在使用这个 jsfiddle 示例( http://jsfiddle.net/6kEpp/1/ )并尝试将其应用于没
使用 orbitcontrols.js(带有 THREE.js),我想在代码中实现与旋转鼠标滚轮相同的效果。例如,我想调用 camera.zoomIn() 之类的东西,让它向目标移动一段设定的距离。有
我已经创建了 map ,如 this link 所示并且运行良好。 但问题是,它只能以一种方式放大(只会变大)。我怎样才能让它以任何一种方式工作? 可能就像我们在 google map 上(加号 -
我正在寻找与 autocad ... 或 solidworks 类似的体验 基本上是内容大小(保持宽高比)Xsize * Ysize 并放大特定区域 并且我已经将 ruby/rails 作为我选择
在bootstrap的重置部分有一个 .clearfix { *zoom: 1; } 请问这里*zoom 和 zoom 有什么区别? 我很感激任何回答。 最佳答案 这是一个 css hack,这意味着
我在单独的子图中有 3 轴加速度计时间序列数据(t,x,y,z)的图,我想一起缩放。也就是说,当我在一个图上使用“缩放到矩形”工具时,当我释放鼠标时,所有 3 个图都会一起缩放。 以前,我只是使用不同
有没有一种简单的方法可以在页面刚加载时默认自动查看 Mapbox map 的所有标记...?这是我的 map :http://www.geometry.be/urbanmaestro/v7/非常感谢您
我已经使用 UIWebView 在 html 文件中设置了以下视口(viewport)标签。 现在,当用户选择时,我得到如图所示的效果。我想禁用此效果但仍然可以放大。 尝试将 UIWebView 的
我现在使用 Core-plot 进行 iPhone 图表开发。但它有一些我无法达到的要求。 我现在使用CorePlot 0.4,示例代码AAPLot来开发 请看下面的图片,然后你就会知道我的问题是什么
最新版本的 Google 地球附带了一项名为“缩放时自动倾斜”的功能。如果启用,Google Earth 会在您拉近表面时自动将相机倾斜到地平线。可以从 GUI 中禁用此功能(首选项 -> 导航选项卡
我找到了使用 rel="smallImage:image1.jpg" 等链接更改缩放图像的方法,但我是在运行时创建图像并将其添加到页面,所以页面首次加载时链接不会存在(这似乎需要存在)。当我在运行时生
我正在使用 ImageView 支持缩放。现在我正在扩展 ImageView 以便我可以在 canvas 上绘图。目前我有 setImageResource 设置一个 drawable 和在 onDr
在缩放行为上手动设置比例后,如何触发缩放事件? var zoom = d3.behavior.zoom() .scaleExtent([0.5, 4]) .on('zoom', onz
我有这个简单的测试代码: ul{ float:left; margin:0; list-style:none; paddi
我正在尝试实现一个具有以下外观的移动网站: 一个固定的标题 可滚动、可缩放的内容 首次加载页面时内容缩小 我一直在试验 IScroll 4,结果似乎不错,但有一个问题我找不到解决办法。我页面的内容是用
嗨,我是 iOS 初学者,在我的项目中,我以编程方式添加了一个 Collection View ,并且已成功添加。 我的要求是,当我单击 UICollectionViewCell 时,它将像下面的第二
遵循此处的建议:How to disable double click zoom for d3.behavior.zoom? 我在页面加载时禁用了双击缩放行为: https://bl.ocks.org
当用户使用鼠标滚轮滚入和滚出时,您可以调整缩放速度吗? 我的理解是 zoom.on (https://github.com/mbostock/d3/wiki/Zoom-Behavior#wiki-on
关于 css 样式和在浏览器中放大和缩小,我遇到了既有趣又奇怪的问题。 我创建了一个 Material ui 卡片,点击它时背景颜色会随着动画而改变。 动画效果很好,但如果您放大或缩小页面,浏览器会在
我将 JQTouch 用于 iPhone 应用程序。 JQtouch 默认情况下禁用捏合和缩放页面的可能性。对于一页(包含大图像),我需要启用捏合和缩放功能。这很容易: var viewport =
我是一名优秀的程序员,十分优秀!