編輯:關於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控件 <a href="http://lib.csdn.net/base/15" class="replace_word" title="undefined" target="_blank" >android</a>: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仿微信圖片點擊全屏效果,謝謝大家的閱讀。
一、 Service簡介 Service是android 系統中的四大組件之一(Activity、Service、BroadcastReceiver、ContentPr
首先我們看一下什麼叫做透明的進度對話框:接下來我們講一下如何創建:1、使用Eclipse創建一個新的Android 項目,使用Android
有很多機油刷了miui後恢復的時候經常會遇到:檢查modem內部版本失敗 modem內部版本不匹配。遇到這種情況解決方法很簡單,下面來分享下經驗:找到線刷工
Service翻譯成中文是服務,熟悉Windows 系統的同學一定很熟悉了。Android裡的Service跟Windows裡的Service功能差不多,就是一個不可見的