1 简介
本篇主要分析源码中的demo.
2 主界面LauncherActivity
class LauncherActivity extends ListActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, options));
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {..}
3 SimpleSampleActivity
use
// The MAGIC happens here!
mAttacher = new PhotoViewAttacher(mImageView);
// Lets attach some listeners, not required though!
mAttacher.setOnMatrixChangeListener(new MatrixChangeListener());
字符串的格式化
static final String PHOTO_TAP_TOAST_STRING = "Photo Tap! X: %.2f %% Y:%.2f %% ID: %d";
String.format(PHOTO_TAP_TOAST_STRING, 33.4534, 33.456, 123);
// result : Photo Tap! X: 33.45 % Y:33.46 % ID: 123
static final String SCALE_TOAST_STRING = "Scaled to: %.2ff";
String.format(SCALE_TOAST_STRING, 98.666);
// result : Scaled to: 98.67f
Toast
private Toast mCurrentToast;
private void showToast(CharSequence text) {
if (null != mCurrentToast) {
mCurrentToast.cancel();
}
mCurrentToast = Toast.makeText(SimpleSampleActivity.this, text, Toast.LENGTH_SHORT);
mCurrentToast.show();
}
Menu
android:showAsAction="never"
你的应用程序目标设为蜂巢平台(即 Android 3.0)时,可以利用Action Bar将你的选项菜单项放在Action Bar的右上角,
never:这个值菜单永远不会出现在ActionBar,withText:这个值使菜单和它的图标,菜单文本一起显示等等其他,
而demo中没有用到actionbar
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem zoomToggle = menu.findItem(R.id.menu_zoom_toggle);
assert null != zoomToggle;
// assert <boolean表达式>,为true,则程序继续执行,为false,则程序抛出AssertionError,并终止执行
zoomToggle.setTitle(mAttacher.canZoom() ? R.string.menu_zoom_disable : R.string.menu_zoom_enable); // 改变一个菜单条目的名字
return super.onPrepareOptionsMenu(menu);
}
菜单显示图1
依次表示:是否允许缩放;修改scale_type类型,如
case R.id.menu_scale_fit_start:
mAttacher.setScaleType(ScaleType.FIT_START);
return true;
设置mAttacher类型后,mAttacher的显示便会自动调整为所显示的类型了
点击更多–菜单显示图2
随机缩放大小–nextFloat():in the half-open range [0.0, 1.0).
case R.id.menu_scale_random_animate: // 渐变
case R.id.menu_scale_random: //直接设定
Random r = new Random();
float minScale = mAttacher.getMinimumScale();
float maxScale = mAttacher.getMaximumScale();
float randomScale = minScale + (r.nextFloat() * (maxScale - minScale));
mAttacher.setScale(randomScale, item.getItemId() == R.id.menu_scale_random_animate);
showToast(String.format(SCALE_TOAST_STRING, randomScale));
return true;
display matrix的先保存与后恢复,似乎有点问题啊,获取的是mDrawMatrix的值,但恢复时设置的却是mSuppMatrix。
extract_visible_bitmap
case R.id.extract_visible_bitmap:
try { // 通过imageView.getDrawingCache()获取bmp,获取的是完整的图片bmp
Bitmap bmp = mAttacher.getVisibleRectangleBitmap();
// /storage/emulated/0/Download/photoview-1792004975.png
File tmpFile = File.createTempFile("photoview", ".png",Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
FileOutputStream out = new FileOutputStream(tmpFile);
// 压缩保存bmp,第二个参数 0-100. 0 meaning compress for small size,100为最优
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/png");
share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tmpFile));
startActivity(share);
Toast.makeText(this, String.format("Extracted into: %s", tmpFile.getAbsolutePath()), Toast.LENGTH_SHORT).show();
} catch (Throwable t) {
// ..
}
return true;
onDestroy
// Need to call clean-up
mAttacher.cleanup();
4 ViewPagerActivity
HackyViewPager:是否允许自身的触摸事件
public class HackyViewPager extends ViewPager {
private boolean isLocked;
public HackyViewPager(Context context) {
super(context);
isLocked = false;
}
public HackyViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
isLocked = false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isLocked) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return !isLocked && super.onTouchEvent(event);
}
public void toggleLock() {
isLocked = !isLocked;
}
public void setLocked(boolean isLocked) {
this.isLocked = isLocked;
}
public boolean isLocked() {
return isLocked;
}
}
ViewPagerActivity
public void onCreate(Bundle savedInstanceState) {
mViewPager.setAdapter(new SamplePagerAdapter());
if (savedInstanceState != null) {
boolean isLocked = savedInstanceState.getBoolean(ISLOCKED_ARG, false);
((HackyViewPager) mViewPager).setLocked(isLocked);
}
}
PhotoView的好处是自身便支持各种触摸事件了,而其他ImageView则需要调用才行。
protected void onSaveInstanceState(Bundle outState) {
if (isViewPagerActive()) {
outState.putBoolean(ISLOCKED_ARG, ((HackyViewPager) mViewPager).isLocked());
}
super.onSaveInstanceState(outState);
}
5 RotationSampleActivity
各种旋转角度的处理
@Override
protected void onPause() {
super.onPause();
// Remove any pending posts of callbacks and sent messages whose obj is token. If token is null, all callbacks and messages will be removed.
handler.removeCallbacksAndMessages(null);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, 0, Menu.NONE, "Rotate 10° Right");
menu.add(Menu.NONE, 2, Menu.NONE, "Toggle automatic rotation");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
photo.setRotationBy(10);
return true;
case 2:
toggleRotation();
return true;
}
return super.onOptionsItemSelected(item);
}
private void toggleRotation() {
if (rotating) {
handler.removeCallbacksAndMessages(null); // 停止旋转
} else {
rotateLoop();
}
rotating = !rotating;
}
// 自动旋转
private void rotateLoop() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
photo.setRotationBy(1);
rotateLoop();
}
}, 15);
}
6 AUILSampleActivity
使用UIL框架加载网络图片,universalimageloader
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
PhotoView photoView = (PhotoView) findViewById(R.id.iv_photo);
if (!ImageLoader.getInstance().isInited()) {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).build();
ImageLoader.getInstance().init(config);
}
ImageLoader.getInstance().displayImage("http://pbs.twimg.com/media/Bist9mvIYAAeAyQ.jpg", photoView);
}
7 结尾
写了三篇,总算是将源码涉及到的所有知识点梳理完了,感谢阅读。