Android仿微信图片点击全屏效果

 更新时间:2020年08月28日 09:34:29   作者:王亟亟  
这篇文章主要为大家详细介绍了Android仿微信图片点击全屏效果的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

废话不多说,先看下Android图片点击全屏效果:

先是微信的

再是模仿的

先说下实现原理,再一步步分析

这里总共有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/

总结:

总体实现并不是太难,因为有框架的关系,使得复杂的动画部分不用自己去写,调用下在回调里做业务就行,这里补充下一些过程中用到的技术点

1.图片的缩放模式:
android:scaleType是控制图片如何resized/moved来匹对ImageView的size。

ImageView.ScaleType / android:scaleType值的意义区别:

CENTER /center  按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示

CENTER_CROP / centerCrop  按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)

CENTER_INSIDE / centerInside  将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽

FIT_CENTER / fitCenter  把图片按比例扩大/缩小到View的宽度,居中显示

FIT_END / fitEnd   把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置

FIT_START / fitStart  把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置

FIT_XY / fitXY  把图片不按比例扩大/缩小到View的大小显示

MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。

** 要注意一点,Drawable文件夹里面的图片命名是不能大写的

2.Layout常用的属性:

// 相对于给定ID控件 
android:layout_above 将该控件的底部置于给定ID的控件之上; 
android:layout_below 将该控件的底部置于给定ID的控件之下; 
android:layout_toLeftOf 将该控件的右边缘与给定ID的控件左边缘对齐; 
android:layout_toRightOf 将该控件的左边缘与给定ID的控件右边缘对齐; 
 
android:layout_alignBaseline 将该控件的baseline与给定ID的baseline对齐; 
android:layout_alignTop 将该控件的顶部边缘与给定ID的顶部边缘对齐; 
android:layout_alignBottom 将该控件的底部边缘与给定ID的底部边缘对齐; 
android:layout_alignLeft 将该控件的左边缘与给定ID的左边缘对齐; 
android:layout_alignRight 将该控件的右边缘与给定ID的右边缘对齐; 
// 相对于父组件 
android:layout_alignParentTop 如果为true,将该控件的顶部与其父控件的顶部对齐; 
android:layout_alignParentBottom 如果为true,将该控件的底部与其父控件的底部对齐; 
android:layout_alignParentLeft 如果为true,将该控件的左部与其父控件的左部对齐; 
android:layout_alignParentRight 如果为true,将该控件的右部与其父控件的右部对齐; 
// 居中 
android:layout_centerHorizontal 如果为true,将该控件的置于水平居中; 
android:layout_centerVertical 如果为true,将该控件的置于垂直居中; 
android:layout_centerInParent 如果为true,将该控件的置于父控件的中央; 
// 指定移动像素 
android:layout_marginTop 上偏移的值; 
android:layout_marginBottom 下偏移的值; 
android:layout_marginLeft   左偏移的值; 
android:layout_marginRight   右偏移的值; 

这个例子只是例子,部分坐标和样式是写死的,如果要运用到实际项目中还是要些许就该,在操作的过程中还对加载多图片进行了测试,暂未发生OOM的情况,补上内存使用情况图(一直很稳定)

这里写图片描述

代码地址
源码下载地址

以上就是本文的全部内容,希望能够帮助大家实现Android仿微信图片点击全屏效果,谢谢大家的阅读。

相关文章

  • Android Retrofit2数据解析代码解析

    Android Retrofit2数据解析代码解析

    这篇文章主要介绍了Android Retrofit2数据解析代码解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • Android App设计规范深入讲解

    Android App设计规范深入讲解

    随着安卓智能手机不停的更新换代,安卓手机系统越来越完美,屏幕尺寸也越来越大啦,下面这篇文章主要给大家介绍了关于Android App设计规范的相关资料,需要的朋友可以参考下
    2022-10-10
  • Android解决getExternalStorageDirectory在29后废弃问题(推荐)

    Android解决getExternalStorageDirectory在29后废弃问题(推荐)

    这篇文章主要介绍了Android解决getExternalStorageDirectory在29后废弃问题(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 详解Android中点击事件的几种实现方式

    详解Android中点击事件的几种实现方式

    本篇文章主要介绍了Android中点击事件的实现方式,点击事件的实现分为3中,详细的介绍了三种的用法,有兴趣的可以了解一下。
    2016-12-12
  • Java实现Andriod带看括弧的计算器代码

    Java实现Andriod带看括弧的计算器代码

    这篇文章主要介绍了Java实现Andriod带看括弧的计算器代码的相关资料,需要的朋友可以参考下
    2016-03-03
  • Android Activity与Service通信(不同进程之间)详解

    Android Activity与Service通信(不同进程之间)详解

    这篇文章主要介绍了Android Activity与Service通信(不同进程之间)的相关资料,这里提供了三种方法,需要的朋友可以参考下
    2016-10-10
  • Android开发实现多进程弹窗效果

    Android开发实现多进程弹窗效果

    这篇文章主要为大家详细介绍了Android开发实现多进程弹窗效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Android自定义View仿探探卡片滑动效果

    Android自定义View仿探探卡片滑动效果

    这篇文章主要为大家详细介绍了Android自定义View仿探探卡片滑动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Android获取手机通话记录的方法

    Android获取手机通话记录的方法

    这篇文章主要为大家详细介绍了Android获取手机通话记录的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Android使用URL读取网络资源的方法

    Android使用URL读取网络资源的方法

    这篇文章主要为大家详细介绍了Android使用URL读取网络资源的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10

最新评论