多点触控,改变文字的字体大小
事件描述: 当放下多个手指的时候,记录第一次和第二次触摸屏幕的手指的距离;当这两个手指移动的时候,记录此时两个手指的新距离,新距离除旧距离的比例即为字体放大或者缩小的比例
重点
重写OnTouchEvent() 方法,重写手指按下和移动的方法
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
// 当手指按下的时候,就去获取当前手指的间距
oldDist = spacing(event);
break;
case MotionEvent.ACTION_MOVE:
// 获取当前触摸点的个数
if (event.getPointerCount() >= 2) {
// 如果触摸点>=2 获取当前两个手指的距离,然后进行缩放
float newDist = spacing(event);
zoom(newDist / oldDist);
//重新置位
oldDist = newDist;
}
break;
}
return true;
}
注意:
// 获取触摸事件的类型,如果是单点是event.getAction(),当涉及到多点触控时,就使用getActionMasked来获取触摸事件类型
两种方式
* 一种为 直接将原来的大小乘以比例
* 另一种为 将 px转为sp
float scale = getResources().getDisplayMetrics().density;
网上别人的代码 用于px和dp相互转换
import android.content.Context;
public class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}
//这个得到的不应该叫做密度,应该是密度的一个比例。不是真实的屏幕密度,而是相对于某个值的屏幕密度。
//也可以说是相对密度
/**
* The logical density of the display. This is a scaling factor for the
* Density Independent Pixel unit, where one DIP is one pixel on an
* approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
* providing the baseline of the system's display. Thus on a 160dpi
* screen this density value will be 1; on a 120 dpi screen it would be
* .75; etc.
*
* This value does not exactly follow the real screen size (as given by
* xdpi and ydpi, but rather is used to scale the size of the overall UI
* in steps based on gross changes in the display dpi. For example, a
* 240x320 screen will have a density of 1 even if its width is
* 1.8", 1.3", etc. However, if the screen resolution is increased to
* 320x480 but the screen size remained 1.5"x2" then the density would
* be increased (probably to 1.5).
*/
/**
* 显示器的逻辑密度,这是【独立的像素密度单位(首先明白dip是个单位)】的一个缩放因子,
* 在屏幕密度大约为160dpi的屏幕上,一个dip等于一个px,这个提供了系统显示器的一个基线(这句我实在翻译不了)。
* 例如:屏幕为240*320的手机屏幕,其尺寸为 1.5"*2" 也就是1.5英寸乘2英寸的屏幕
* 它的dpi(屏幕像素密度,也就是每英寸的像素数,dpi是dot per inch的缩写)大约就为160dpi,
* 所以在这个手机上dp和px的长度(可以说是长度,最起码从你的视觉感官上来说是这样的)是相等的。
* 因此在一个屏幕密度为160dpi的手机屏幕上density的值为1,而在120dpi的手机上为0.75等等
* (这里有一句话没翻译,实在读不通顺,不过通过下面的举例应该能看懂)
* 例如:一个240*320的屏幕尽管他的屏幕尺寸为1.8"*1.3",(我算了下这个的dpi大约为180dpi多点)
* 但是它的density还是1(也就是说取了近似值)
* 然而,如果屏幕分辨率增加到320*480 但是屏幕尺寸仍然保持1.5"*2" 的时候(和最开始的例子比较)
* 这个手机的density将会增加(可能会增加到1.5)
*/
计算公式
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 宽度(PX)
int height = metric.heightPixels; // 高度(PX)
float density = metric.density; // 密度(0.75 / 1.0 / 1.5)
int densityDpi = metric.densityDpi; // 密度DPI(120 / 160 / 240)
* 方式一
package com.example.zoomtextview.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.TextView;
public class ZoomTextView2 extends TextView {
private float oldDistance;
private float newDistance;
float textSize = this.getTextSize();
public ZoomTextView2(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public ZoomTextView2(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public ZoomTextView2(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_POINTER_DOWN:
oldDistance = spacing(event);
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() >= 2) {
newDistance = spacing(event);
zoomTex(newDistance/oldDistance);
oldDistance = newDistance;
}
break;
default:
break;
}
return true;
}
private void zoomTex(float f) {
textSize *= f;
this.setTextSize(px2sp(getContext(),textSize));
}
private int px2sp(Context context, float textSize2) {
// TODO Auto-generated method stub
float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (textSize2/scaledDensity);
}
/**
* 两指之间距离
* @param event
* @return
*/
private float spacing(MotionEvent event) {
// TODO Auto-generated method stub
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x*x + y*y);
}
}
方式二:
package com.example.zoomtextview; import android.content.Context; import android.util.AttributeSet; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; /** * Created by Administrator on 2016/8/31. */ public class ZoomTextView extends TextView { private float textSize = this.getTextSize(); private float oldDist; public ZoomTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public ZoomTextView(Context context, AttributeSet attrs) { super(context, attrs); } public ZoomTextView(Context context) { super(context); } /** * 处理TextView的触摸事件 */ @Override public boolean onTouchEvent(MotionEvent event) { //在一开始,计算当前字体的大小 /*if (textSize == 0) { textSize = this.getTextSize(); Log.i("text", ""+this.getTextSize()); }*/ // 获取触摸事件的类型,如果是单点是event.getAction(),当涉及到多点触控时,就使用getActionMasked来获取触摸事件类型 switch (event.getActionMasked()) { case MotionEvent.ACTION_POINTER_DOWN: // 当手指按下的时候,就去获取当前手指的间距 oldDist = spacing(event); break; case MotionEvent.ACTION_MOVE: // 获取当前触摸点的个数 if (event.getPointerCount() >= 2) { // 如果触摸点>=2 获取当前两个手指的距离,然后进行缩放 float newDist = spacing(event); zoom(newDist / oldDist); //重新置位 oldDist = newDist; } break; } return true; } /** * 不断进行缩放 * * @param f */ private void zoom(float f) { textSize *= f; this.setTextSize(px2sp(getContext(), textSize)); } /** * 将px值转换为sp值,保证文字大小不变 * * @param pxValue * (DisplayMetrics类中属性scaledDensity) * @return */ public static int px2sp(Context context, float pxValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (pxValue / fontScale + 0.5f); } /** * 计算两个手指的大小 * * @param event * @return */ private float spacing(MotionEvent event) { //获取第一个点的x坐标和第二个点的x坐标 float x = event.getX(0) - event.getX(1); //分别获取y坐标 float y = event.getY(0) - event.getY(1); //使用勾股定理计算两点距离 return (float) Math.sqrt(x*x+y*y); } }