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' 实现的,这边不做教程了给出传送门:)
总结:
总体实现并不是太难,因为有框架的关系,使得复杂的动画部分不用自己去写,调用下在回调里做业务就行,这里补充下一些过程中用到的技术点
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仿微信图片点击全屏效果,谢谢大家的阅读。