目标=把helloworld的文字变成可以缩放的,并可以移动文字块[scrollable]。
测试=需要能实体手机,虚拟机似乎不能进行触摸缩放测试。
版本=android 2.3.3,target=android-10
效果图
关键点
=============main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scrollbars = "vertical" android:text="@string/hello" /> </LinearLayout>
package com.ex.a1205; import android.app.Activity; import android.graphics.Point; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.util.Log; import android.util.TypedValue; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.View.OnTouchListener; import android.widget.TextView; public class A1Activity extends Activity implements OnTouchListener { enum Mode { NONE, DRAG, ZOOM } Mode mode = Mode.NONE; static final int MIN_FONT_SIZE = 20; static final int MAX_FONT_SIZE = 120; PointF start = new PointF(); Point tvPos0 = new Point(); Point tvPos1 = new Point(); Point tvPosSave = new Point(); float oldDist = 1f; int scrWidth; int scrHeight; TextView textView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textView = (TextView) findViewById(R.id.text); loadDoc(); textView.setOnTouchListener(this); Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)) .getDefaultDisplay(); scrWidth = display.getWidth(); scrHeight = display.getHeight(); } private void loadDoc() { StringBuilder sb = new StringBuilder(); for (int i = 0; i <= 30; i++) { sb.append("Line: ").append(i).append("\n"); } textView.setText(sb.toString()); } public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: start.set(event.getX(), event.getY()); tvPos0.set((int) event.getX(), (int) event.getY()); mode = Mode.DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); if (oldDist > 10f) { mode = Mode.ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = Mode.NONE; tvPos1.set(tvPosSave.x, tvPosSave.y); break; case MotionEvent.ACTION_MOVE: if (mode == Mode.DRAG) { doScroll(event); } else if (mode == Mode.ZOOM) { doZoom(event); } break; } return true; } private void doScroll(MotionEvent event) { int xe = (int) event.getX(); int ye = (int) event.getY(); int txtHeight = textView.getLineHeight() * (textView.getLineCount() - 2); int xt = tvPos1.x + tvPos0.x - xe; int yt = tvPos1.y + tvPos0.y - ye; if (xt < -textView.getRight()) { xt = -textView.getRight() + 20; } else if (xt > scrWidth) { xt = scrWidth - 20; } if (yt < -textView.getBottom()) { yt = -textView.getBottom() + textView.getLineHeight(); } else if (yt > txtHeight) { yt = txtHeight; } textView.scrollTo(xt, yt); tvPosSave.set(xt, yt); // log("to(", xt, ",", yt, ")" // , " tHt=", txtHeight // ); } void log(Object... objs) { StringBuilder sb = new StringBuilder(); for (Object obj : objs) { sb.append(obj); } Log.d(A1Activity.class.getSimpleName(), sb.toString()); } private void doZoom(MotionEvent event) { float newDist = spacing(event); if (newDist > 10f) { float scale = newDist / oldDist; if (scale > 1) { scale = 1.1f; } else if (scale < 1) { scale = 0.95f; } float currSize = textView.getTextSize() * scale; if ((currSize < MAX_FONT_SIZE && currSize > MIN_FONT_SIZE) || (currSize >= MAX_FONT_SIZE && scale < 1) || (currSize <= MIN_FONT_SIZE && scale > 1)) { textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, currSize); } } } /** Determine the space between the first two fingers */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } }