废话不多说,先看下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实现点击图片全屏展示效果,包括了android实现点击图片全屏展示效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了android实现点击图片全屏展示的具体代码,供大家参考,具体内容如下 MainActivity: 布局文件: style: 效果图: 没点击: 点击后: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Android仿微信视屏悬浮窗效果,包括了Android仿微信视屏悬浮窗效果的使用技巧和注意事项,需要的朋友参考一下 在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点。 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频通话时,将远端视频以悬浮窗形式展示,根据他的代码我进行了部分简化 1
本文向大家介绍Android仿微信朋友圈点击加号添加图片功能,包括了Android仿微信朋友圈点击加号添加图片功能的使用技巧和注意事项,需要的朋友参考一下 本文为大家分享了类似微信朋友圈,点击+号图片,可以加图片功能,供大家参考,具体内容如下 xml: NinePhotoView.java Measure 我们的子View三个一排,而且都是正方形,所以我们上面通过循环很好去得到所有子View的
本文向大家介绍Android仿微信微博多图展示效果,包括了Android仿微信微博多图展示效果的使用技巧和注意事项,需要的朋友参考一下 1.简介 这是一个用于实现像微信朋友圈和微博的类似的九宫格图片展示控件,通过自定义viewgroup实现,使用方便。 多图根据屏幕适配,单张图片时需要自己指定图片的宽高; 2.使用方法 引用: compile 'com.w4lle.library:NineLayo
本文向大家介绍Android仿微信朋友圈图片查看器,包括了Android仿微信朋友圈图片查看器的使用技巧和注意事项,需要的朋友参考一下 再看文章之前,希望大家先打开自己的微信点到朋友圈中去,仔细观察是不是发现朋友圈里的有个“九宫格”的图片区域,点击图片又会跳到图片的详细查看页面,并且支持图片的滑动和缩放?这个功能是不是很常用呢?!那么我今天正好做了这个Demo,下面为大家讲解一下。首先按照惯例先看
本文向大家介绍Android GridView仿微信朋友圈显示图片,包括了Android GridView仿微信朋友圈显示图片的使用技巧和注意事项,需要的朋友参考一下 最近项目要求上传多图并且多图显示,而且要规则的显示,就像微信朋友圈的图片显示一样。 利用GridView再适合不过了,GridView可以动态加载图片的数量,而且还比较规律,下面说一下自己的思路: 1.获取网络图片 2.初始化gri