一、效果图展示
二、分析
很多时候如果View超出了屏幕,我们希望能够靠两根手指对View进行放大和缩小。放大缩小的话我们就要用到矩阵 Matrix 的知识。
三、代码实现
监听手指的手势,需要用到一个类:
//拉伸手势
ScaleGestureDetector scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
isScaling = true;
float scaleFactor = detector.getScaleFactor();
if (getMatrixScaleY() * scaleFactor > 3) {
scaleFactor = 3 / getMatrixScaleY();
}
if (firstScale) {
anchorX = detector.getCurrentSpanX();
anchorY = detector.getCurrentSpanY();
firstScale = false;
}
if (getMatrixScaleY() * scaleFactor < 0.5) {
scaleFactor = 0.5f / getMatrixScaleY();
}
matrix.postScale(scaleFactor, scaleFactor, anchorX, anchorY);
//计算拉伸
computecellLocation();
invalidate();
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
isScaling = false;
firstScale = true;
}
});
当然如果你要确保监听的到,需要在 onTouchEvent() 里面加上一句话:
//监听拉伸
scaleGestureDetector.onTouchEvent(event);
然后回调到 onScale() 的时候,我们需要加一个边界判断,放大比例最大是3倍,缩小比例最小是 0.5 ,这个值可以写成变量。
(anchorX 和 anchorY 我以为是两根手指的中心点,参照这个点放大。很遗憾并不是,我修改为(5000, 5000),貌似还是从(0, 0)开始放大)
matrix.postScale(scaleFactor, scaleFactor, anchorX, anchorY);
这句话就是整个核心,post 在网络请求有一个意思是添加,这里可以这样理解,在原有的放缩比上增加当前放缩比例。记录完之后,我们需要拿出来进行计算:
/**
* 计算每一个cell的位置
*/
private void computecellLocation() {
float scaleX = getMatrixScaleX();
float scaleY = getMatrixScaleY();
int columnCount = 0;
int groupSize = cellGroups.size();
for (int i = 0; i < groupSize; i++) {
CellGroup cellGroup = cellGroups.get(i);
cellGroup.setTitle("第" + (i + 1) + "期");
cellGroup.setLocation(0, leftBarWidth, (int) (cellHeight * scaleY * i + topBarHeight), (int) (cellHeight * scaleY * (i + 1) + topBarHeight));
List cells = cellGroup.getCells();
int cellSize = cells.size();
columnCount = cellSize;
for (int j = 0; j < cellSize; j++) {
Cell cell = cells.get(j);
cell.setLocation(
(int) (cellWidth * scaleX * j + leftBarWidth),
(int) (cellWidth * scaleX * (j + 1) + leftBarWidth),
(int)(cellHeight * scaleY * i + topBarHeight),
(int)(cellHeight * scaleY * (i + 1) + topBarHeight));
}
}
//计算顶部栏的位置
int size = topCells.size();
for (int i = 0; i < size; i++) {
Cell cell = topCells.get(i);
cell.setLocation((int) (cellWidth * scaleX * i + leftBarWidth), (int) (cellWidth * scaleX * (i + 1) + leftBarWidth), 0, topBarHeight);
}
maxWidth = (int) (columnCount * cellWidth * scaleX + leftBarWidth);
maxHeight = (int) (groupSize * cellHeight * scaleY + topBarHeight);
}
|
这个方法我们一直在修改,View放大了,并不是View的宽高变化了,只是我们记录的数据要改变。比如我们的宽以前是20,现在放大了3倍,那么就是宽变成了60。
左侧栏的宽度和顶部栏的高度不变化我们就不需要乘以比例。
以上就是所有代码。我在之前的主干分支上又切了一个 “伸缩版” 的分支,可以下载下来研究研究,好用给个star。3q
github地址