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的情况,补上内存使用情况图(一直很稳定)

这里写图片描述

代码地址:https://github.com/ddwhan0123/BlogSample/tree/master/ImitateWeChatImage
源码下载地址:https://github.com/ddwhan0123/BlogSample/blob/master/ImitateWeChatImage/ImitateWeChatImage.zip?raw=true

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

(0)

相关推荐

  • Android ActionBarActivity设置全屏无标题的方法总结

    Android ActionBarActivity设置全屏无标题的方法总结 新建的Activity继承自ActionBarActivity,设置全屏无标题本来很简单的事,但是没想到app竟然无缘无故的挂,要么就是白屏一片,要么就是黑屏.坑了我一个多小时!!! 原因是ActionBarActivity设置theme的时候只能使用v7包里的Theme.AppCompat***开头的主题,因此设置全屏无标题的话需要自定义个style: <style name="ActionBarFullScre

  • Android编程实现WebView自适应全屏方法小结

    本文实例讲述了Android编程实现WebView自适应全屏的方法.分享给大家供大家参考,具体如下: 第一种: settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); 第二种: WebSetting settings = webView.getSettings(); settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); 把所有内容放在we

  • Android 设置应用全屏的两种解决方法

    在开发中我们经常需要把我们的应用设置为全屏,有两种方法,一中是在代码中设置,另一种方法是在配置文件里改! 一.在代码中设置: 复制代码 代码如下: package com.android.tutor;  import android.app.Activity;  import android.os.Bundle;  import android.view.Window;  import android.view.WindowManager;  public class OpenGl_Lesson

  • android activity设置无标题实现全屏

    Activity设置全屏和无标题栏,要用到andorid.view.Window和Android.view.WindowManager. Window.FEATURE_NO_TITLE表示无标题栏. WindowManager.LayoutParams.FLAG_FULLSCREEN表示全屏. 具体用法如下: 1.设置全屏可以使用如下代码: getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager

  • android 设置全屏的两种方法

    现在android的每一个项目都会需要设置为全屏,现在介绍两种设置为全屏的方式. 一.在配置文件中设置android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" 如: 二.在activity中设置 这两种方式都可以设置全屏,任选其一即可.

  • android全屏去掉title栏的多种实现方法

    1.实现应用中的所有activity都全屏 在manifest中直接加入 复制代码 代码如下: android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 2.实现单个activity全屏 复制代码 代码如下: requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.TYPE_STATUS_BAR

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

    废话不多说,先看下效果: 先是微信的 再是模仿的 先说下实现原理,再一步步分析 这里总共有2个Activity一个就是主页,一个就是显示我们图片效果的页面,参数通过Intent传送,素材内容均来自网络,(感谢聪明的蘑菇) 图片都是Glide异步下的,下的,下的重要的事情说三次,然后就是用动画做放大操作然后显示出来了(并没有做下载原图的实现,反正也是一样 下载下来Set上去而且动画都不需要更简便). OK,我们来看分析下 obj,目录下分别创建了2个对象,一个用来使用来处理显示页面的图片尺寸信息以

  • Android仿微信图片点击浏览的效果

    本篇我们来做一个类似于微信的图片点击浏览的效果,点击小图图片后会放大至全屏显示,且中间有一个2D平滑过渡的效果. 思路如下: 首先,从图片缩略界面跳转到图片详情页面,应该是从一个Activity跳转到另外一个Activity,应该图片详情页面也有很多操作,用View或者Dialog不是很好.所以现在难点就是,如何使得前一个界面的ImageView在另外一个界面做缩放切割动画. 其次,一般缩略界面的ImageView的是正方形的,并且是CENTER_CROP缩放属性的.CENTER_CROP属性会

  • 关于微信上网页图片点击全屏放大效果

    实现微信上网页的图片点击后全屏还可以可以缩放,这个功能是别人做的,可是捏点击后屏幕直接黑屏了,图片没有显示出来.这个代码在网上搜一下,挺多类似的. 先上代码. function arrayToJson(o) { var r = []; if (typeof o == "string") return "\"" + o.replace(/([\'\"\\])/g, "\\$1").replace(/(\n)/g, "\

  • Android仿微信图片选择器ImageSelector使用详解

    今天给大家介绍一个仿微信的图片选择器:ImageSelector.ImageSelector支持图片的单选.限数量的多选和不限数量的多选.支持图片预览和图片文件夹的切换.在上一篇文章 <Android 实现一个仿微信的图片选择器> 中我介绍了ImageSelector的实现思路和分析了它的核心代码,有兴趣的同学可以看一下.完整的代码放在了GitHub,欢迎大家下载和使用.本篇文章为大家介绍ImageSelector的具体使用方式. 先上效果图: 1.引入依赖 在Project的build.gr

  • IOS中实现图片点击全屏预览

    如果你感觉累,那就对了那是因为你在走上坡路..这句话似乎有点道理的样子,时常提醒自己无论走到哪都不要忘记自己当初为什么出发.有时想想感觉有的东西可以记录一下,就把它记录下来吧,这次想写一下关于单张图片点击全屏预览的问题,网上查了一些大神写的有的功能确实很强大但自己暂时想要的只是简单的功能就好,还有些方法自己也没弄出想要的效果,最后写了一个比较简单的点击单张图片的全屏预览和双指捏合缩小放大,可能有时要对图片做一些处理,这里放大后只是显示同一张图片并未做处理,下面直接贴出代码 // // ViewC

  • Android仿微信图片上传带加号且超过最大数隐藏功能

    1.仿照微信空间上传图片,显示图片数量以及超过最大,上传按钮隐藏功能 2.上效果图 3.上代码,主要是Adapter类 /** * Created by zhangyinlei on 2018/3/2 0002. */ public class AlbumSelectedShowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static int TYPE_ADD = 0;//添加图片 privat

  • Android仿微信右上角点击加号弹出PopupWindow

    本文实例为大家分享了Android仿微信右上角点击加号弹出展示的具体代码,供大家参考,具体内容如下 一.要弹出的布局,随便设计 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@drawable/my_ph

  • Android仿微信朋友圈点击评论自动定位到相关行功能

    最近闲来无事,随便看看各种UI实现的代码 本文涉及到的相关代码已经上传到 https://github.com/r17171709/android_demo/tree/master/WeixinEditText 打开你的微信朋友圈,点击评论,你就会发现有一个小细节:文本输入框的高度恰好定位到这条信息的底部位置 这个实现起来其实很简单,咱们就来看看吧 最简单的RecyclerView 依然是先实现RecyclerView.跟朋友圈一样,我们也把头给加上去,这样我们在点第一条信息的时候,效果会更好一

  • Android仿微信朋友圈点击加号添加图片功能

    本文为大家分享了类似微信朋友圈,点击+号图片,可以加图片功能,供大家参考,具体内容如下 xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto

  • Android仿微信图片选择器

    很多项目要用到图片选择控件,每次都要写一大堆逻辑.于是基于图片选择组件(PhotoPicker)封装了一个控件PhotoUploadView.方便简易,一键集成,几句代码就可以添加类似微信的图片选择控件了.下面介绍一下该控件有些什么特点以及怎么使用.先看图: 效果如上图,点击加号弹出选择框,目前提供了两种形式,一个如图所见的PopupWindow,另一个是MaterialDialog,选择拍照或者从图库获取,从图库获取后就进入图二,选择完之后就图三或图四这里因为很多项目需要不一样,所以特别封装了

随机推荐