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

寫了三篇,總算是將源碼涉及到的所有知識點梳理完了,感謝閱讀。

點擊下載!

發佈了20 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章