[Android]网页内图片点击查看大图/识别二维码/下载

场景

链接:https://upload-images.jianshu.io/upload_images/564272-8c7ae161a750783b.gif?imageMogr2/auto-orient/strip

项目中的广告详情页面是个webView加载的富文本,包含图片,需要点击查看大图,长按识别二维码功能。

实现

  • webView基础设置
        val webView = fragment.binding.webView
        webView.settings.javaScriptEnabled = true
        webView.settings.builtInZoomControls = false
        webView.settings.displayZoomControls = true
        webView.settings.setSupportZoom(false)//不支持缩放功能
        webView.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY //取消滚动条白边效果
        webView.webChromeClient = WebChromeClient()
        webView.webViewClient = MyWebViewClient()
        webView.addJavascriptInterface(MJavascriptInterface(fragment.activity,fragment),"imagelistener")
        webView.settings.defaultTextEncodingName = "UTF-8"
        webView.settings.blockNetworkImage = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW  //注意安卓5.0以上的权限
        }
        if (detail.content.checkNotNull()) {
            val css = "<style>*{padding: 0;margin: 0}#webview_content_wrapper{margin: 10px 15px 0 15px;}; p{color: #333333;line-height: 2em;font-size:14px;opacity: 1;}; img {margin-top: 13px;margin-bottom: 15px;width: 100%;}</style>"
            val html = css + "<body><div id='webview_content_wrapper'>" + detail.content + "</div></body>"
            webView.loadDataWithBaseURL(null, ImageUtil.getNewContent(html), "text/html", "UTF-8", null)
        }
        webView.setOnLongClickListener(object : View.OnLongClickListener {
            override fun onLongClick(v: View?): Boolean {
                val result =webView.hitTestResult
                if (!result.checkNotNull()) {
                    return false
                }
                val type = result.type
                when (type) {
                // 超链接
                    WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE,/*带有链接的图片类型*/WebView.HitTestResult.IMAGE_TYPE -> {
                        // 处理长按图片的菜单项
                        val coverUrl = result.extra
                        if (URLUtil.isValidUrl(coverUrl) || coverUrl.startsWith("data:image")) {
                            UiUtils.webViewLongClick(fragment, webView.context, coverUrl)
                            return true
                        }
                    }
                }
                return false
            }
        })
  • webViewLongClick

    /*网页长按弹窗(识别二维码,下载图片)*/
    @JvmStatic
    fun webViewLongClick(fragment: BaseFragment, context: Context, coverUrl: String) {
        openSelect(fragment, context, coverUrl)
    }

    /*网页长按弹窗(识别二维码,下载图片)*/
    private fun openSelect(fragment: BaseFragment, context: Context, coverUrl: String) {
        val dialog = BottomSheetDialog(context)
        val layoutView = LayoutInflater.from(context).inflate(R.layout.dialog_select_qrcode_down_img, null)
        layoutView.findViewById<TextView>(R.id.tv_qrcode).setOnClickListener {
            //图片url
                  Glide.with(context.applicationContext).asBitmap().load(coverUrl)
                          .into(object : SimpleTarget<Bitmap>() {
                              override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                                  CodeUtils.analyzeBitmap(resource, object : CodeUtils.AnalyzeCallback {
                                      override fun onAnalyzeSuccess(mBitmap: Bitmap, result: String) {
                                          fragment.start(WebFragment.newInstance("", result))
                                      }

                                      override fun onAnalyzeFailed() {
                                          "未识别到二维码".toast()
                                      }

                                  })
                                  dialog.dismiss()
                              }
                          })
        }
        layoutView.findViewById<TextView>(R.id.tv_download).setOnClickListener {
            if (coverUrl.startsWith("data:image")) {
                var fileName: String? = null
                if (MimeTypeMap.getFileExtensionFromUrl(coverUrl) == "") {
                    fileName = System.currentTimeMillis().toString() + ".jpg"
                } else {
                    fileName = System.currentTimeMillis().toString() + "." + MimeTypeMap.getFileExtensionFromUrl(coverUrl)
                }
                val file = BitmapUtils.saveBitmapFile(AndroidtoJs.stringToBitmap(coverUrl), DownLoadImageRunnable.SAVE_DOWNLOAD_IMAGE_PATH + fileName)
                if (file.checkNotNull()) {
                    "已保存".toast()
                } else {
                    "保存失败".toast()
                }
            } else {
                ImageUtil.downLoadImg(context, coverUrl)
            }
            dialog.dismiss()
        }
        dialog.setContentView(layoutView)
        dialog.show()
    }

  • 弹窗布局dialog_select_qrcode_down_img.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_qrcode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:includeFontPadding="false"
        android:padding="15dp"
        android:text="识别二维码"
        android:textColor="@color/color_333333"
        android:textSize="@dimen/sp_14" />

    <View
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_1"
        android:layout_marginLeft="@dimen/dp_15"
        android:layout_marginRight="@dimen/dp_15"
        android:background="@color/color_f5f5f5" />

    <TextView
        android:id="@+id/tv_download"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:includeFontPadding="false"
        android:padding="15dp"
        android:textColor="@color/color_333333"
        android:textSize="@dimen/sp_14"
        android:text="下载图片" />
</LinearLayout>
  • MyWebViewClient

import android.graphics.Bitmap;
import android.webkit.WebView;
import android.webkit.WebViewClient;


/**
 * Created by Administrator on 2017/2/10.
 */

public class MyWebViewClient extends WebViewClient {
    @Override
    public void onPageFinished(WebView view, String url) {
        view.getSettings().setJavaScriptEnabled(true);
        super.onPageFinished(view, url);
        addImageClickListener(view);//待网页加载完全后设置图片点击的监听方法
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        view.getSettings().setJavaScriptEnabled(true);
        super.onPageStarted(view, url, favicon);
    }

    private void addImageClickListener(WebView webView) {
        webView.loadUrl("javascript:(function(){" + "var objs = document.getElementsByTagName(\"img\");" +
                " " + " var array=new Array(); " +
                " for(var j=0;j<objs.length;j++){ " + "array[j]=objs[j].src;" + " }  " +
                "for(var i=0;i<objs.length;i++)  " + "{" + "  objs[i].onclick=function()  " + "  {  " + "   " +
                " window.imagelistener.openImage(this.src,array);  " + "  }  " + "}" + "})()");
    }
}
  • MJavascriptInterface

import android.app.Activity;
import android.widget.ImageView;

import com.xlj.app.global.base.BaseFragment;
import com.xlj.app.widget.ninegrid.ImageInfo;

import java.util.ArrayList;

public class MJavascriptInterface {
    private Activity context;
    private BaseFragment fragment;
    private static final String TAG = "SIMON";

    ArrayList<String> images = new ArrayList<>();

    public MJavascriptInterface(Activity context, BaseFragment fragment) {
        this.context = context;
        this.fragment = fragment;
    }

    @android.webkit.JavascriptInterface //必须添加
    public void openImage(String img, String[] array) {
        int index = 0;
        ArrayList<ImageInfo> imageInfo = new ArrayList<>();
        for (int i = 0; i < array.length; i++) {
            ImageInfo imInfo = new ImageInfo();
            imInfo.thumbnailUrl = array[i];
            imInfo.bigImageUrl = array[i];
            imageInfo.add(imInfo);
            if (array[i].equals(img)) {
                index = printArray(array, img);
            }
        }
        ImageView imageView = new ImageView(context);
        fragment.previewPhoto(imageView, imageInfo, index, false, true,true);
    }

    //遍历数组
    private int printArray(String[] array, String value) {
        for (int i = 0; i < array.length; i++) {
            if (array[i].equals(value)) {
                return i;
            }
        }
        return -1;//当if条件不成立时,默认返回一个负数值-1
    }
}
  • 大图查看

    //图片预览
    fun previewPhoto(clickImageView: ImageView, imageInfo: List<ImageInfo>, index: Int, finishAnimator: Boolean = true, isShowShare: Boolean = false,isSeeCode:Boolean=false) {
        if (imageInfo.isNotEmpty()) {
            val info: ImageInfo = imageInfo[0]
            imageInfo.forEach {
                it.imageViewWidth = clickImageView.width
                it.imageViewHeight = clickImageView.height
                val points = IntArray(2)
                clickImageView.getLocationInWindow(points)
                info.imageViewX = points[0]
                info.imageViewY = points[1] - StatusBarUtil.getStatusBarHeight(activity)
            }
            val intent = Intent(context, ImagePreviewActivity::class.java)
            val bundle = Bundle()
            bundle.putSerializable(ImagePreviewActivity.IMAGE_INFO, imageInfo as Serializable)
            bundle.putInt(ImagePreviewActivity.CURRENT_ITEM, index)
            bundle.putBoolean(ImagePreviewActivity.FINISH_ANIMATION, finishAnimator)
            bundle.putBoolean(ImagePreviewActivity.IS_SHOW_SHARE, isShowShare)
            bundle.putBoolean(ImagePreviewActivity.IS_SEE_CODE, isSeeCode)
            intent.putExtras(bundle)
            context!!.startActivity(intent)
            activity!!.overridePendingTransition(0, 0)
        }
    }

  • 下面是图片预览的activity -----ImagePreviewActivity

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.bigkoo.alertview.AlertView;
import com.bigkoo.alertview.OnItemClickListener;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.dtr.zxing.utils.CodeUtils;
import com.kaopiz.kprogresshud.KProgressHUD;
import com.tencent.qcloud.tim.uikit.component.photoview.downloadimg.ImageUtil;
import com.tencent.qcloud.tim.uikit.utils.ToastUtil;
import com.umeng.analytics.MobclickAgent;
import com.umeng.socialize.UMShareAPI;
import com.xlj.app.R;
import com.xlj.app.global.Constant;
import com.xlj.app.mvvm.main.activity.WebActivity;
import com.xlj.app.mvvm.main.fragment.WebFragment;
import com.xlj.app.utils.EventBusUtils;
import com.xlj.app.utils.Toast.ToastUtils;
import com.xlj.app.widget.ninegrid.ImageInfo;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;

public class ImagePreviewActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {

    public static final String IMAGE_INFO = "IMAGE_INFO";
    public static final String CURRENT_ITEM = "CURRENT_ITEM";
    public static final String FINISH_ANIMATION = "FINISH_ANIMATION";
    public static final String IS_SHOW_SHARE = "IS_SHOW_SHARE";
    //是否有 识别二维码
    public static final String IS_SEE_CODE = "IS_SEE_CODE";
    public static final int ANIMATE_DURATION = 200;

    private RelativeLayout rootView;

    private ImagePreviewAdapter imagePreviewAdapter;
    private List<ImageInfo> imageInfo;
    private int currentItem;
    private int imageHeight;
    private int imageWidth;
    private int screenWidth;
    private int screenHeight;
    private boolean isUseFinishAnimator, isShowShare, isSeeCode;
    private KProgressHUD loading;
    private String bigImageUrl;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_preview);
        loading = KProgressHUD.create(ImagePreviewActivity.this).setStyle(KProgressHUD.Style.SPIN_INDETERMINATE).setWindowColor(ImagePreviewActivity.this.getResources().getColor(R.color.color_trans)).setCancellable(false);

        ViewPager viewPager = findViewById(R.id.viewPager);
        final TextView tv_pager = findViewById(R.id.tv_pager);
        ImageView imgShare = findViewById(R.id.img_share);
        rootView = findViewById(R.id.rootView);

        DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        screenWidth = metric.widthPixels;
        screenHeight = metric.heightPixels;

        Intent intent = getIntent();
        imageInfo = (List<ImageInfo>) intent.getSerializableExtra(IMAGE_INFO);
        currentItem = intent.getIntExtra(CURRENT_ITEM, 0);
        isUseFinishAnimator = intent.getBooleanExtra(FINISH_ANIMATION, true);
        isShowShare = intent.getBooleanExtra(IS_SHOW_SHARE, false);//是否有弹窗菜单(转发。保存)
        isSeeCode = intent.getBooleanExtra(IS_SEE_CODE, false);//是否有弹窗菜单(转发。保存)

        imgShare.setVisibility(isShowShare ? View.VISIBLE : View.GONE);
        imagePreviewAdapter = new ImagePreviewAdapter(this, imageInfo);
        imagePreviewAdapter.setIsShowOrginal(isShowShare);
        imagePreviewAdapter.setSeeCode(isSeeCode);
        viewPager.setAdapter(imagePreviewAdapter);
        viewPager.setCurrentItem(currentItem);
        viewPager.getViewTreeObserver().addOnPreDrawListener(this);
        viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                currentItem = position;
                tv_pager.setText(String.format(getString(R.string.select), currentItem + 1, imageInfo.size()));

            }
        });
        tv_pager.setText(String.format(getString(R.string.select), currentItem + 1, imageInfo.size()));
        bigImageUrl = imageInfo.get(currentItem).thumbnailUrl;
        imgShare.setOnClickListener(v -> {
            if (bigImageUrl != null && !"".equals(bigImageUrl)) {
                menuPop(v, bigImageUrl);
            }
//            DialogUtils.umShare(ImagePreviewActivity.this,imgShare.getContext(),bigImageUrl,"分享到", loading);
/*            new Thread(() -> ImageUtil.url2Bitmap(ImagePreviewActivity.this, bigImageUrl, new ImageUtil.GetCallBackInterface<Bitmap>() {
                @Override
                public void onSuccess(Bitmap bitmap) {
                    //点击分享
                    if (bitmap != null) {
                        runOnUiThread(() -> DialogUtils.shareWeChatDialog(ImagePreviewActivity.this, bitmap, "分享到").show());
                    }
                }

                @Override
                public void onFail(String s) {

                }
            })).start();*/
        });
    }

    private void menuPop(View v, String bigImageUrl) {
        if (isSeeCode) {
            showSeeCodeDialog(v);
            return;
        }
        new AlertView("操作", null, "取消", null, new String[]{"转发", "保存"}, v.getContext(), AlertView.Style.ActionSheet, new OnItemClickListener() {
            @Override
            public void onItemClick(Object o, int position) {
                if (position == -1) return;
                if (position == 0) {
                    //转发
                    if (currentItem == -1) return;
                    EventBusUtils.forwordImgMessage(currentItem);
                    onBackPressed();
                } else {
                    if (bigImageUrl.contains("http")) {
                        ImageUtil.downLoadImg(ImagePreviewActivity.this, bigImageUrl);
                    } else {
                        try {
                            FileInputStream fis = new FileInputStream(bigImageUrl);
                            Bitmap bitmap = BitmapFactory.decodeStream(fis);
                            boolean succ = ImageUtil.saveImageToGallery(ImagePreviewActivity.this, bitmap);
                            String tip = "";
                            if (succ) {
                                tip = "已保存到相册";
                            } else {
                                tip = "保存失败";
                            }
                            ToastUtil.toastShortMessage(tip);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).setCancelable(true).show();
    }

    private void showSeeCodeDialog(View v) {
        new AlertView("操作", null, "取消", null, new String[]{"识别二维码", "保存"}, v.getContext(), AlertView.Style.ActionSheet, new OnItemClickListener() {
            @Override
            public void onItemClick(Object o, int position) {
                if (position == -1) return;
                if (position == 0) {
                    // 识别二维码
                    Glide.with(v.getContext()).asBitmap().load(bigImageUrl)
                            .into(new SimpleTarget<Bitmap>() {

                                @Override
                                public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                                    CodeUtils.analyzeBitmap(resource, new CodeUtils.AnalyzeCallback() {
                                        @Override
                                        public void onAnalyzeSuccess(Bitmap mBitmap, String result) {
                                            WebActivity.Companion.start(v.getContext(),result,"");
                                        }

                                        @Override
                                        public void onAnalyzeFailed() {
                                            ToastUtils.showShortToast(v.getContext(), "未识别到二维码");
                                        }
                                    });
                                }
                            });
                } else {
                    if (bigImageUrl.contains("http")) {
                        ImageUtil.downLoadImg(ImagePreviewActivity.this, bigImageUrl);
                    } else {
                        try {
                            FileInputStream fis = new FileInputStream(bigImageUrl);
                            Bitmap bitmap = BitmapFactory.decodeStream(fis);
                            boolean succ = ImageUtil.saveImageToGallery(ImagePreviewActivity.this, bitmap);
                            String tip = "";
                            if (succ) {
                                tip = "已保存到相册";
                            } else {
                                tip = "保存失败";
                            }
                            ToastUtil.toastShortMessage(tip);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }).setCancelable(true).show();
    }

    @Override
    public void onBackPressed() {
        finishActivityAnim();
    }

    /**
     * 绘制前开始动画
     */
    @Override
    public boolean onPreDraw() {
        rootView.getViewTreeObserver().removeOnPreDrawListener(this);
        final View view = imagePreviewAdapter.getPrimaryItem();
        final ImageView imageView = imagePreviewAdapter.getPrimaryImageView();
        computeImageWidthAndHeight(imageView);

        final ImageInfo imageData = imageInfo.get(currentItem);
        final float vx = imageData.imageViewWidth * 1.0f / imageWidth;
        final float vy = imageData.imageViewHeight * 1.0f / imageHeight;
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);
        valueAnimator.addUpdateListener(animation -> {
            long duration = animation.getDuration();
            long playTime = animation.getCurrentPlayTime();
            float fraction = duration > 0 ? (float) playTime / duration : 1f;
            if (fraction > 1) {
                fraction = 1;
            }
            view.setTranslationX(evaluateInt(fraction, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2, 0));
            view.setTranslationY(evaluateInt(fraction, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2, 0));
            view.setScaleX(evaluateFloat(fraction, vx, 1));
            view.setScaleY(evaluateFloat(fraction, vy, 1));
            view.setAlpha(fraction);
            rootView.setBackgroundColor(evaluateArgb(fraction, Color.TRANSPARENT, Color.BLACK));
        });
        addIntoListener(valueAnimator);
        valueAnimator.setDuration(ANIMATE_DURATION);
        valueAnimator.start();
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        MobclickAgent.onPageStart(this.getClass().getSimpleName());
        MobclickAgent.onResume(this);
        if (loading.isShowing()) {
            loading.dismiss();
        }
    }


    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPageEnd(this.getClass().getSimpleName());
        MobclickAgent.onPause(this);
    }

    public void longClick(View v) {
        if (!isShowShare) return;//
        if (bigImageUrl != null && !"".equals(bigImageUrl)) {
            menuPop(v, bigImageUrl);
        }
    }

    /**
     * activity的退场动画
     */
    public void finishActivityAnim() {
        if (!isUseFinishAnimator) {
            finish();
            overridePendingTransition(0, 0);
        } else {
            final View view = imagePreviewAdapter.getPrimaryItem();
            final ImageView imageView = imagePreviewAdapter.getPrimaryImageView();
            computeImageWidthAndHeight(imageView);

            final ImageInfo imageData = imageInfo.get(currentItem);
            final float vx = imageData.imageViewWidth * 1.0f / imageWidth;
            final float vy = imageData.imageViewHeight * 1.0f / imageHeight;

            final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);
            valueAnimator.addUpdateListener(animation -> {
                long duration = animation.getDuration();
                long playTime = animation.getCurrentPlayTime();
                float fraction = duration > 0 ? (float) playTime / duration : 1f;
                if (fraction > 1) {
                    fraction = 1;
                }
                view.setTranslationX(evaluateInt(fraction, 0, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2));
                view.setTranslationY(evaluateInt(fraction, 0, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2));
                view.setScaleX(evaluateFloat(fraction, 1, vx));
                view.setScaleY(evaluateFloat(fraction, 1, vy));
                view.setAlpha(1 - fraction);
                rootView.setBackgroundColor(evaluateArgb(fraction, Color.BLACK, Color.TRANSPARENT));
            });
            addOutListener(valueAnimator);
            valueAnimator.setDuration(ANIMATE_DURATION);
            valueAnimator.start();
        }
    }

    /**
     * 计算图片的宽高
     */
    private void computeImageWidthAndHeight(ImageView imageView) {

        // 获取真实大小
        Drawable drawable = imageView.getDrawable();
        int intrinsicHeight = drawable.getIntrinsicHeight();
        int intrinsicWidth = drawable.getIntrinsicWidth();
        // 计算出与屏幕的比例,用于比较以宽的比例为准还是高的比例为准,因为很多时候不是高度没充满,就是宽度没充满
        float h = screenHeight * 1.0f / intrinsicHeight;
        float w = screenWidth * 1.0f / intrinsicWidth;
        if (h > w) h = w;
        else w = h;

        // 得出当宽高至少有一个充满的时候图片对应的宽高
        imageHeight = (int) (intrinsicHeight * h);
        imageWidth = (int) (intrinsicWidth * w);
    }

    /**
     * 进场动画过程监听
     */
    private void addIntoListener(ValueAnimator valueAnimator) {
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                rootView.setBackgroundColor(0x0);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
    }

    /**
     * 退场动画过程监听
     */
    private void addOutListener(ValueAnimator valueAnimator) {
        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                rootView.setBackgroundColor(0x0);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                finish();
                overridePendingTransition(0, 0);
            }

            @Override
            public void onAnimationCancel(Animator animation) {
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
    }

    /**
     * Integer 估值器
     */
    public Integer evaluateInt(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int) (startInt + fraction * (endValue - startInt));
    }

    /**
     * Float 估值器
     */
    public Float evaluateFloat(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }

    /**
     * Argb 估值器
     */
    public int evaluateArgb(float fraction, int startValue, int endValue) {
        int startA = (startValue >> 24) & 0xff;
        int startR = (startValue >> 16) & 0xff;
        int startG = (startValue >> 8) & 0xff;
        int startB = startValue & 0xff;

        int endA = (endValue >> 24) & 0xff;
        int endR = (endValue >> 16) & 0xff;
        int endG = (endValue >> 8) & 0xff;
        int endB = endValue & 0xff;

        return (startA + (int) (fraction * (endA - startA))) << 24
                | (startR + (int) (fraction * (endR - startR))) << 16
                | (startG + (int) (fraction * (endG - startG))) << 8
                | (startB + (int) (fraction * (endB - startB)));
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data);
    }

}

  • 预览的xml文件activity_preview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <com.xlj.app.widget.ninegrid.preview.HackyViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:id="@+id/tv_pager"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:text="1/4"
        android:textColor="#ffffff"
        android:textSize="20sp" />
    <ImageView
        android:id="@+id/img_share"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_margin="10dp"
        android:padding="5dp"
        android:src="@drawable/ic_pic_more" />
</RelativeLayout>

  • 用到了一个自定义的HackyViewPager

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/** 修复图片在ViewPager控件中缩放报错的BUG */
public class HackyViewPager extends ViewPager {

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

    public HackyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        try {
            return super.onTouchEvent(ev);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return super.onInterceptTouchEvent(ev);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return false;
    }
}

参考链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349