エレガントに!大きな画像でAndroidと長いロードな写真

私たちは常に開発時間をやっていることは、必然的に画像をImageViewのサイズよりも小さい場合には、当然の私たちが直接ロードショーを行くことは非常に幸せになれるケースの負荷イメージが発生します。

私たちは絵をロードしたい場合はしかし、それはあまりにも多くのメモリやパフォーマンスのオーバーヘッドを取るだろう、悪い視覚効果をもたらすだろう示すために直接ImageViewのとImageViewのサイズよりもはるかに大きいです。

でも、この絵はクラッシュOOMにプログラムを引き起こすのに十分な大きさです。今回我々は、画像の特別な処理のために必要があります。
エレガントに! 大きな画像でAndroidと長いロードな写真

#Aの画像圧縮

画像が大きすぎる、私はそれを小さな画像を圧縮する方法を求めていました。古い鉄は、このアイデアは完全に間違っていないです。

BitmapFactoryこのクラスは、ビットマップを作成するために使用される分析方法の複数(decodeResource、decodeStream、decodeFile等)を提供します。

私たちは、絵のソースに応じた分析方法を選択することができます。

  • たとえば、ネットワークからの映像ならば、あなたはdecodeStreamメソッドを使用することができます。
  • 画像内のSDカードの場合は、decodeFile方法を選択することができます。
  • 画像内のリソースファイルの場合は、decodeResourceメソッドを使用することができます。
    これらのメソッドは、イメージが大きすぎる場合、それはOOMにつながる、作成したビットマップ用のメモリを割り当てます。

BitmapFactoryこれらのメソッドは、私たちが絵を解決するために、オプションのパラメータBitmapFactory.Optionsを提供しています。このパラメータは、プロパティinSampleSizeがあり、このプロパティは、画像を圧縮するために私たちを助けることができます。

inSampleSizeの効果を説明するために、我々は、栗を与えることができます。
例えば、我々は2048ているinSampleSizeが4セット1536の写真は、あなたがこの画像圧縮512置くことができる 384、4回に減少それぞれの長さを、共有メモリは16倍減少しています。
これは、inSampleSizeの役割はinSampleSize平方メモリのシェアを減らし、画像inSampleSize時間の長さを短くすることが明らかです。
与えられた値が1未満であれば、公式文書用の値も1に、デフォルトのinSampleSizeの値が1に等しいよりも大きくなければなりません要件の一部を作っinSampleSize。
そしてinSampleSizeが2の倍数である必要があり、そうでない場合、それは自動的にそのような所定の値として、この値は下から2の最も近い倍数になるであろう値は3であり、その値は、最終的なinSampleSize 2であろう。

もちろん、このinSampleSizeは、我々は写真の元のサイズを得ることができるようにだけベストを尽くすし、必要に応じて、その後に圧縮することができない値。Googleは、私たちはそれを上だと思うのに役立ちます、心配しないでください!BitmapFactory.OptionsがプロパティinJustDecodeBoundsを持って、このプロパティがtrueの場合、私たちの現在の境界線がちょうどBitmapFactory解像度の画像方法を返す、その後、現在の画像のサイズを取得することを示すことは非常に軽量であるヌル、ある時間であります方法。我々は画像サイズを取得するのは非常に幸せになることができるように、以下のように、コードは次のとおりです。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 当前只为获取图片的边界大小
BitmapFactory.decodeResource(getResources(), R.drawable.bigpic, options);
int outHeight = options.outHeight;
int outWidth = options.outWidth;
String outMimeType = options.outMimeType;

画像のサイズを取得し、我々は必要な圧縮の必要なサイズを計算することができます。

private int caculateSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int sampleSize = 1;
        int picWidth = options.outWidth;
        int picHeight = options.outHeight;
        if (picWidth > reqWidth || picHeight > reqHeight) {
            int halfPicWidth = picWidth / 2;
            int halfPicHeight = picHeight / 2;
            while (halfPicWidth / sampleSize > reqWidth || halfPicHeight / sampleSize > reqHeight) {
                sampleSize *= 2;
            }
        }
        return sampleSize;
}

ここでは、完全なコードは次のとおりです。

        mIvBigPic = findViewById(R.id.iv_big_pic);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; // 当前只为获取图片的边界大小
        BitmapFactory.decodeResource(getResources(), R.drawable.bigpic, options);
        int outHeight = options.outHeight;
        int outWidth = options.outWidth;
        String outMimeType = options.outMimeType;
        System.out.println("outHeight = " + outHeight + " outWidth = " + outWidth + " outMimeType = " + outMimeType);
        options.inJustDecodeBounds = false;
        options.inSampleSize = caculateSampleSize(options, getScreenWidth(), getScreenHeight());
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bigpic, options);
        mIvBigPic.setImageBitmap(bitmap);

ほとんどこっちにそのようなイメージ。

#第二に、地元のショー

時々、圧縮によって良い結果を得ることができますが、時には効果は、私たちが直接圧縮を表示する場合は、この写真は完全に盲目である限り、そのように描く、このような長い画像絵画として、良いようではありません、それは経験に影響を及ぼしています。その後、我々は絵を見るための方法を示すために、地元のショー、そしてスライドを採用することができます。

BitmapRegionDecoder使用内部のアンドロイドは、ローカルにその矩形領域を示す、画像を表示します。この機能を達成するには、画像表示領域を設定する別の方法を設定する方法が必要になります。

初期
BitmapRegionDecoder等、初期化着信ファイルパス、ファイル記述子とファイルストリーム入力ストリームをサポートするためのnewInstanceのシリーズを提供します

例えば:

mRegionDecoder = BitmapRegionDecoder.newInstance(InputStreamの、偽) ;
このアプローチの上方に着信画像を解決し、次のステップは、表示領域を設定することです。

ビットマップビットマップ= mRegionDecoder.decodeRegion(mRect、sOptions );
パラメータまず、レクト、2つのパラメータはBitmapFactory.Optionsあり、同様にinSampleSize、inPreferredConfigを制御するために使用することができます。ここで、画面の大部分の正面の写真を示す簡単な例です。

try {
        BitmapRegionDecoder regionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);
        BitmapFactory.Options options1 = new BitmapFactory.Options();
        options1.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = regionDecoder.decodeRegion(new Rect(0, 0, getScreenWidth(), getScreenHeight()), options1);
        mIvBigPic.setImageBitmap(bitmap);
    } catch (IOException e) {
        e.printStackTrace();
    }

我々は完全に無害画像を表示するためにもちろん、これは、単に最も簡単な使い方です!Keguan、Shaoanwuzaoは、未来はすでに明らかです!今、私たちは地域のショーを達成できることを、我々はビューをカスタマイズすることができ、あなたは私たちの指は、さまざまな分野のショーの写真をスライドさせることができると。はい!もちろん。だから我々はそれを継続していきます!

上記の分析によると、我々は思考の習慣の非常に認識しています。

セット交差点画像を提供するステップと、
onTouchEventを書き換え、ユーザのジェスチャの移動に応じて、画像の表示領域を変更する;
各更新エリアパラメータ、コール無効化、onDraw regionDecoder.decodeRegionの内部の後にビットマップを取得するために、描画する
ADOを、直接コードに:

public class BigImageView extends View {
    private static final String TAG = "BigImageView";

    private BitmapRegionDecoder mRegionDecoder;
    private int mImageWidth, mImageHeight;
    private Rect mRect = new Rect();
    private static BitmapFactory.Options sOptions = new BitmapFactory.Options();
    {
        sOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
    }

    public BigImageView(Context context) {
        this(context, null);
    }

    public BigImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BigImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    public void setInputStream(InputStream inputStream) {
        try {
            mRegionDecoder = BitmapRegionDecoder.newInstance(inputStream, false);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = false;
            BitmapFactory.decodeStream(inputStream, null, options);
            mImageHeight = options.outHeight;
            mImageWidth = options.outWidth;

            requestLayout();
            invalidate();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    int downX = 0;
    int downY = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = (int) event.getX();
                downY = (int) event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                int curX = (int) event.getX();
                int curY = (int) event.getY();

                int moveX = curX - downX;
                int moveY = curY - downY;

                onMove(moveX, moveY);

                System.out.println(TAG + " moveX = " + moveX + " curX = " + curX + " downX = " + downX);

                downX = curX;
                downY = curY;
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

    private void onMove(int moveX, int moveY) {
        if (mImageWidth > getWidth()) {
            mRect.offset(-moveX, 0);
            checkWidth();
            invalidate();
        }

        if (mImageHeight > getHeight()) {
            mRect.offset(0, -moveY);
            checkHeight();
            invalidate();
        }

    }

    private void checkWidth() {
        Rect rect = mRect;
        if (rect.right > mImageWidth) {
            rect.right = mImageWidth;
            rect.left = mImageWidth - getWidth();
        }

        if (rect.left < 0) {
            rect.left = 0;
            rect.right = getWidth();
        }
    }

    private void checkHeight() {
        Rect rect = mRect;
        if (rect.bottom > mImageHeight) {
            rect.bottom = mImageHeight;
            rect.top = mImageHeight - getHeight();
        }

        if (rect.top < 0) {
            rect.top = 0;
            rect.bottom = getWidth();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        mRect.left = 0;
        mRect.top = 0;
        mRect.right = width;
        mRect.bottom = height;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Bitmap bitmap = mRegionDecoder.decodeRegion(mRect, sOptions);
        canvas.drawBitmap(bitmap, 0, 0, null);
    }
}

上記ソースコードによると:

;実際の画像の幅と高さを取得setInputStream法、内部初期BitmapRegionDecoder

開始画像領域の表示を制御するために初期値を割り当てるRECT onMeasure方法。

onTouchEventモニタユーザのジェスチャは、画像表示領域を変更するためのパラメータを変更し、境界検出、そして最終的に無効化RECT;
ビットマップのRectを取得し、onDrawの内部に描画します。

#最後に、
学習は、私たちの学習パスを共有するために、アリのP7の建築家、単純な問題ではありません

エレガントに! 大きな画像でAndroidと長いロードな写真

Androidのプログラマーとして、学ぶべき多くのものがあります。

あなたは、高度なアップグレードを学ぶのを助けるために、独自のAndroid整理学習コンテンツをリリース

  • フェイス質問集
  • エントリーレベルの書籍PDF:Javaの、C、C ++
  • 注目のAndroidの高度なPDFブック
  • アリの仕様書
  • Androidの開発スキル
  • 高度なPDF Daquanの
  • シニアアドバンスドビデオ
  • ソース
  • ビデオ学習アルゴリズム
  • 継続するには

今のトレンドがあり学んでいるフラッター、kotinやその他の情報を学ぶために検索時間節約、照合されており、

あなたが必要としている場合は、次のことができます+コメントのように指して心配私私は、その後、民間の手紙

エレガントに! 大きな画像でAndroidと長いロードな写真

エレガントに! 大きな画像でAndroidと長いロードな写真

エレガントに! 大きな画像でAndroidと長いロードな写真

おすすめ

転載: blog.51cto.com/14606040/2462580