1. 程式人生 > >模仿微信圖片點選全屏效果

模仿微信圖片點選全屏效果

昨天想著模仿寫些什麼,然後覺得什麼仿京東啊,仿美團之類的外面都有,正好又找到點資源就寫了這篇“高仿微信圖片放大”

廢話不多說,先看下效果:

先是微信的

這裡寫圖片描述

再是模仿的

這裡寫圖片描述

包目錄

這裡寫圖片描述

先說下實現原理,再一步步分析

這裡總共有2個Activity一個就是主頁,一個就是顯示我們圖片效果的頁面,引數通過Intent傳送,素材內容均來自網路,(感謝聰明的蘑菇) 圖片都是Glide非同步下的,下的,下的重要的事情說三次,然後就是用動畫做放大操作然後顯示出來了(並沒有做下載原圖的實現,反正也是一樣 下載下來Set上去而且動畫都不需要更簡便)。

OK,我們來看分析下

obj,目錄下分別建立了2個物件,一個用來使用來處理顯示頁面的圖片尺寸資訊以及位置資訊,還有一個是用來附帶URL和解析度

Config這個類就是我們的URL了沒其他什麼內容。

我們一個一個頁面來看,先看MainActivity

他做的事情很簡單,就是把下個頁面的一些資訊初始化一下然後通過Intent傳過去,本身不做什麼多餘操作

package wjj.com.imitatewechatimage.activity;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

import
wjj.com.imitatewechatimage.R; import com.apkfuns.logutils.LogUtils; import com.bumptech.glide.Glide; import wjj.com.imitatewechatimage.Config; import wjj.com.imitatewechatimage.obj.ImageInfoObj; import wjj.com.imitatewechatimage.obj.ImageWidgetInfoObj; public class MainActivity extends AppCompatActivity
implements View.OnClickListener {
private ImageView imageView; private ImageInfoObj imageInfoObj; private ImageWidgetInfoObj imageWidgetInfoObj; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findId(); init(); Listener(); } private void findId() { imageView = (ImageView) findViewById(R.id.imageView); } private void init() { Glide.with(MainActivity.this).load(Config.IMAGE_URL).placeholder(R.mipmap.maimai).into(imageView); imageInfoObj = new ImageInfoObj(); imageInfoObj.imageUrl = Config.IMAGE_URL; imageInfoObj.imageWidth = 1280; imageInfoObj.imageHeight = 720; imageWidgetInfoObj = new ImageWidgetInfoObj(); imageWidgetInfoObj.x = imageView.getLeft(); imageWidgetInfoObj.y = imageView.getTop(); imageWidgetInfoObj.width = imageView.getLayoutParams().width; imageWidgetInfoObj.height = imageView.getLayoutParams().height; } private void Listener() { imageView.setOnClickListener(this); } @Override protected void onResume() { super.onResume(); LogUtils.d("--->MainActivity onResume"); } @Override protected void onPause() { super.onPause(); LogUtils.d("--->MainActivity onPause"); } @Override protected void onDestroy() { super.onDestroy(); LogUtils.d("--->MainActivity onDestroy"); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.imageView: //攜帶引數跳轉 Intent intent = new Intent(MainActivity.this, howImageActivity.class); intent.putExtra("imageInfoObj", imageInfoObj); intent.putExtra("imageWidgetInfoObj", imageWidgetInfoObj); startActivity(intent); break; default: break; } } }

具體業務類ShowImageActivity

public class ShowImageActivity extends AppCompatActivity {
    private RelativeLayout MainView;
    private ImageView showImageView;
    private ImageInfoObj imageInfoObj;
    private ImageWidgetInfoObj imageWidgetInfoObj;
    Button button;

    // 螢幕寬度
    public float Width;
    //原圖高
    private float y_img_h;
    // 螢幕高度
    public float Height;
    private float size, size_h, img_w, img_h;
    protected float to_x = 0;
    protected float to_y = 0;
    private float tx;
    private float ty;


    private final Spring spring = SpringSystem
            .create()
            .createSpring()
            .addListener(new ExampleSpringListener());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_how_image);
        LogUtils.d("--->ShowImageActivity onCreate");
        findId();
        init();
        Listener();
    }

    private void findId() {
        MainView = (RelativeLayout) findViewById(R.id.MainView);
        button = (Button) findViewById(R.id.button);
    }

    private void init() {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        Width = dm.widthPixels;
        Height = dm.heightPixels;

        imageInfoObj = (ImageInfoObj) getIntent().getSerializableExtra("imageInfoObj");
        imageWidgetInfoObj = (ImageWidgetInfoObj) getIntent().getSerializableExtra("imageWidgetInfoObj");
        if (imageInfoObj == null) {
            LogUtils.d("--->imageInfoObj==null");
        }
        if (imageWidgetInfoObj == null) {
            LogUtils.d("--->imageWidgetInfoObj==null");
        }

        showImageView = new ImageView(this);
        showImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

        Glide.with(ShowImageActivity.this).load(imageInfoObj.imageUrl).into(showImageView);

        img_w = imageWidgetInfoObj.width;
        img_h = imageWidgetInfoObj.height - 300;
        size = Width / img_w;
        y_img_h = imageInfoObj.imageHeight * Width / imageInfoObj.imageWidth;
        size_h = y_img_h / img_h;

        RelativeLayout.LayoutParams p = new RelativeLayout.LayoutParams((int) imageWidgetInfoObj.width,
                (int) imageWidgetInfoObj.height);
        p.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
        p.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
        showImageView.setLayoutParams(p);
        p.setMargins((int) imageWidgetInfoObj.x,
                (int) imageWidgetInfoObj.y, (int) (Width - (imageWidgetInfoObj.x + imageWidgetInfoObj.width)),
                (int) (Height - (imageWidgetInfoObj.y + imageWidgetInfoObj.height)));
        MainView.addView(showImageView);

        new Handler().post(new Runnable() {
            public void run() {
                ShowImageView();
            }
        });
    }

    private void Listener() {
        showImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShowImageView();
            }
        });

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShowImageView();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        LogUtils.d("--->ShowImageActivity onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        LogUtils.d("--->ShowImageActivity onPause");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LogUtils.d("--->ShowImageActivity onDestroy");
    }

    private class ExampleSpringListener implements SpringListener {

        @Override
        public void onSpringUpdate(Spring spring) {
            double CurrentValue = spring.getCurrentValue();
            float mappedValue = (float) SpringUtil.mapValueFromRangeToRange(CurrentValue, 0, 1, 1, size);
            float mapy = (float) SpringUtil.mapValueFromRangeToRange(CurrentValue, 0, 1, 1, size_h);
            showImageView.setScaleX(mappedValue);
            showImageView.setScaleY(mapy);
            if (CurrentValue == 1) {
//                showImageView.setVisibility(View.GONE);
            }
        }

        @Override
        public void onSpringAtRest(Spring spring) {

        }

        @Override
        public void onSpringActivate(Spring spring) {

        }

        @Override
        public void onSpringEndStateChange(Spring spring) {

        }
    }

    //實現效果
    private void MoveView() {

        ObjectAnimator.ofFloat(MainView, "alpha", 0.8f).setDuration(0).start();
        MainView.setVisibility(View.VISIBLE);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(
                ObjectAnimator.ofFloat(showImageView, "translationX", tx).setDuration(200),
                ObjectAnimator.ofFloat(showImageView, "translationY", ty).setDuration(200),
                ObjectAnimator.ofFloat(MainView, "alpha", 1).setDuration(200)

        );
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                showImageView.setScaleType(ImageView.ScaleType.FIT_XY);
                spring.setEndValue(1);
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        set.start();

    }

    //關閉頁面
    private void MoveBackView() {
        AnimatorSet set = new AnimatorSet();
        set.playTogether(
                ObjectAnimator.ofFloat(showImageView, "translationX", to_x).setDuration(200),
                ObjectAnimator.ofFloat(showImageView, "translationY", to_y).setDuration(200)
        );
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                finish();
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        set.start();
    }

    //具體動畫處理類
    private void ShowImageView() {
        if (spring.getEndValue() == 0) {
            //彈動摩擦力
            spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(300, 5));
            //動畫結束後出現的位置
            tx = 0;
            ty = Height / 2 - (imageWidgetInfoObj.y + img_h + 600);
            MoveView();
            return;
        }
        spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(1, 5));
        spring.setEndValue(0);
        new Handler().post(new Runnable() {
            public void run() {
                MoveBackView();
            }
        });

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {

            showImageView.setVisibility(View.VISIBLE);
            ShowImageView();

        }
        return true;
    }

}

大致流程:
1.在 init()獲取了螢幕資訊,上一個類傳來的引數,以及對座標點進行了一些計算 ,然後用Handler來啟動動畫的效果

2.ShowImageView()處理了動畫的實現,(動畫效果是compile 'com.facebook.rebound:rebound:0.3.8' 實現的,這邊不做教程了給出傳送門:http://facebook.github.io/rebound/

總結:

總體實現並不是太難,因為有框架的關係,使得複雜的動畫部分不用自己去寫,呼叫下在回撥裡做業務就行,這裡補充下一些過程中用到的技術點

這個例子只是例子,部分座標和樣式是寫死的,如果要運用到實際專案中還是要些許就該,在操作的過程中還對載入多圖片進行了測試,暫未發生OOM的情況,補上記憶體使用情況圖(一直很穩定)

這裡寫圖片描述