PhotoView源码分析(3)

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();
    }

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 结尾

写了三篇,总算是将源码涉及到的所有知识点梳理完了,感谢阅读。

点击下载!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值