AndroidシミュレーションInstagramピクチャロードポリシー(ファジイピクチャ占有+ダウンロード進捗バー)

6209 ワード

前言:
InstagramのAndroidクライアントのユーザー体験は素晴らしいので、この3つのポイントを分析しました.
1、スクリーン外画像プリロード
注視画面に表示されている1枚の画像を見ていると、画面の下に引き出されていない画像がバックグラウンドでダウンロードされているという意味で、この機能はRecyclerViewのプリロード機能を使ってよくシミュレートされています.
2、ファジイ占拠
まず、他の人の動きを取得すると、その人のユーザー名、顔、画像url、画像のサムネイルが同時に戻ってきて、画面にサムネイルが表示されますが、実際の画像は非同期でダウンロードされ、ダウンロードが終わった後に置き換える前のぼやけた図です.
3、ダウンロード進捗ヒント
Instagramには、現在のダウンロードの進捗率を示す白い進捗バーがあります.
この3つの主要な機能について、私はすでに似たような効果をすべてシミュレートしました.本稿では、私の前の2つのブログに基づいて、ファジイビットマップの実現過程を重点的に説明します.前の2つのブログを参照してください.-『okhttp 3を使用してAndroid画像フレームワークPicassoのダウンロードとバッファを作成します.』『Android画像のロードにパーセンテージ進捗バーを追加します(Picasso+Okhttp 3)』
効果:
プロジェクトgithubアドレス:https://github.com/AlexZhuo/AlxPicassoProgress
実現構想:
まず1つ目は、画像のurl情報、ユーザ情報、コメント情報などをサムネイルと同期して取得することであり、サーバがJSON文字列データを発揮する際に、jpg形式のサムネイル(ここでは解像度25 x 25)をBase 64を用いてJSONのあるフィールドに可読文字列に圧縮して置くことであり、1つの画像を文字列に詰め込んで送ることに相当する.クライアントは、Base 64でエンコードされたサムネイルを受信して復号し、メインスレッドでこのサムネイルを拡大+ガウスブラーしてImageViewに表示し、Piassoはダウンロードが完了した後、元のbitmapを実際のピクチャに置き換え、効果の表示を完了する.
このため、サーバ側が行うべき準備は、次のとおりです.
1、事前に画像を等比例のサムネイルに切り取り、Base 64で圧縮してデータベースに保存する
2、JSON文字列の送信時に、上のBase 64文字列を画像の実際のURLとともに送信する
3、urlを使用して本物のピクチャを要求する場合、Httpの応答ヘッダはContent-Longthフィールドを追加してこのピクチャの完全なサイズを提示し、ダウンロード率を計算する
Android側はPicasso 2とOkHttp 3の2つのフレームワークとカスタム進捗バーコントロールを追加するだけでこの効果を達成できます.
注意:25 x 25のサムネイルをImageViewに直接配置すれば、理論的には効果も実現できますが、ぼやけてしまうのは非常に見苦しいです.私の方法は、25 x 25のサムネイルを300 x 300の大図に変えてから、ガウスぼやけという章300 x 300の大図を、ぼやけ半径をできるだけ大きくすることです.私の上のdemoでは、ガウスファジイを実現していますが、普通のファジイアルゴリズムを使用しています.ファジイアルゴリズムが出てからInsほど柔らかくないので、機会があればそのファジイアルゴリズムを更新します.
次はいくつかの主要なコードを貼って、その他のコードはgithubの上で見てください
Base 64文字をBitmapに変換する方法:
public static Bitmap base64ToBitmap(String sourceBase64){
        if(TextUtils.isEmpty(sourceBase64)) sourceBase64 = "/9j/4AAQSkZJRgABAQEAYABgAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2ODApLCBxdWFsaXR5ID0gOTAK/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgAMgAyAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJD...    ";
        byte[] sourceBytes = Base64.decode(sourceBase64.getBytes(),Base64.DEFAULT);
        if(sourceBytes == null || sourceBytes.length == 0)return null;
        Bitmap bitmap = BitmapFactory.decodeByteArray(sourceBytes,0,sourceBytes.length);
        if(bitmap == null)return null;
        if(bitmap.getHeight()<2)return null;
        return bitmap;
    }
ここでヒントを与えます.一般的にJPGはBase 64を使って圧縮すると/9 j/で始まるので、これを使って変換が正しいかどうかを判断することができます.Base 64を圧縮した後に多くの'/'文字が現れます.'/'と書かないでください.そうしないとBitmapを変換できません.
小さなBitmapを大きなBitmapに変換する方法:
 /**
     *     bitmap,            
     * @param bitmap
     * @param widthRatio     ,    1 ,    1 
     * @param heightRatio
     * @return
     */
    public static Bitmap scaleBitmap(Bitmap bitmap, float widthRatio, float heightRatio) {
        Matrix matrix = new Matrix();
        matrix.postScale(widthRatio,heightRatio);
        return Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
    }

ガウスぼかしの方法:
 if (Build.VERSION.SDK_INT > 16) {
            Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);

            final RenderScript rs = RenderScript.create(context);
            final Allocation input = Allocation.createFromBitmap(rs, sentBitmap, Allocation.MipmapControl.MIPMAP_NONE,
                    Allocation.USAGE_SCRIPT);
            final Allocation output = Allocation.createTyped(rs, input.getType());
            final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
            script.setRadius(radius /* e.g. 3.f */);
            script.setInput(input);
            script.forEach(output);
            output.copyTo(bitmap);
            return bitmap;
        }

上記はAndroidオリジナルサポートのガウスアルゴリズムで、下位層はc実装を採用しており、効率が高い.SDKバージョンが17未満であればgithubでif以外を見る方法は、Java実装のファジイアルゴリズムであり、低バージョンのマシンに用いられ、私がdemoで使用しているファジイ半径は8である.
スクリーン外画像のプリロード方法:
このdemoは、効果が明らかなため、プリロード機能は追加されていませんが、実際のプロジェクトではRecyclerViewをコンテナとして使用していますが、RecyclerViewにプリロードを追加する方法は以下の通りです.
まずLayoutManagerをカスタマイズする必要があります
mport android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;


/**
 * Created by Alex on 2016/9/18.
 *      recyclerView     layoutmanager
 */
public class AlxPreloadLinearManager extends LinearLayoutManager{
    private static final int DEFAULT_EXTRA_LAYOUT_SPACE = 1280;

    private int extraLayoutSpace = DEFAULT_EXTRA_LAYOUT_SPACE;

    public AlxPreloadLinearManager(Context context) {
        super(context);
    }

    public AlxPreloadLinearManager(Context context, int extraLayoutSpace) {
        super(context);
        this.extraLayoutSpace = extraLayoutSpace;
    }

    public AlxPreloadLinearManager(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
    }

    public void setExtraLayoutSpace(int extraLayoutSpace) {
        this.extraLayoutSpace = extraLayoutSpace;
    }

    @Override
    protected int getExtraLayoutSpace(RecyclerView.State state) {
        if (extraLayoutSpace > 0) {
            return extraLayoutSpace;
        }
        return DEFAULT_EXTRA_LAYOUT_SPACE;
    }
}
LayoutManager layoutManager = new AlxPreloadLinearManager(context);
int screenHeigth =getScreenHeigth();
if(screenHeigth > 500)((AlxPreloadLinearManager)layoutManager).setExtraLayoutSpace(screenHeight);//            
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);

呼び出し方法:
1行だけでいい:ファジイビット機能AlxPicassoUtilsを追加したい場合.displayImageProgress(url,imageView,progressWheel,textView,base64Str); パラメータは、画像urlアドレス、ImageViewコントロール、円形プログレスバーコントロール、プログレス表示TextView、Base 64により圧縮された画像サムネイルAlxPicassoUtilsである.displayImageProgress(url,imageView,progressWheel,textView); パラメータは、画像urlアドレス、ImageViewコントロール、円形進捗バーコントロール、進捗表示TextView