【Android视图效果】共享元素实现仿微信查看大图效果
在之前的文章中,我們通過動畫實現了這個,具體可以查看【Android 動畫】動畫詳解之仿微信查看大圖效果(四),這里,我們用過度動畫來實現。
什么是共享元素?
它是Android 5.0新加入的一種過度動畫,主要用于2個activity之間,可以共享某些控件,實現無縫轉場的動畫。
如何使用?
1.為共享元素指定統一的 transition name 2.啟動 Activity 時帶上共享元素參數
效果圖
錄制的gif 不是很流暢,實際效果還是很流暢的首先,我們需要一個九宮格,9張圖片
list = new ArrayList<>();list.add("http://img1.imgtn.bdimg.com/it/u=4206294871,879077254&fm=26&gp=0.jpg");list.add("http://img1.imgtn.bdimg.com/it/u=1901690610,3955011377&fm=200&gp=0.jpg");list.add("http://img3.imgtn.bdimg.com/it/u=1546158593,2358526642&fm=200&gp=0.jpg");list.add("http://img0.imgtn.bdimg.com/it/u=3792909229,2321547963&fm=200&gp=0.jpg");list.add("http://img4.imgtn.bdimg.com/it/u=1621655683,865218969&fm=200&gp=0.jpg");list.add("http://img5.imgtn.bdimg.com/it/u=4286838121,1364454560&fm=26&gp=0.jpg");list.add("http://img5.imgtn.bdimg.com/it/u=551944592,1654216059&fm=26&gp=0.jpg");list.add("http://img1.imgtn.bdimg.com/it/u=2550323596,2167297465&fm=200&gp=0.jpg");list.add("http://img4.imgtn.bdimg.com/it/u=952962361,1269259737&fm=26&gp=0.jpg");wxAdapter = new WxAdapter(list);rvWx2.setLayoutManager(new GridLayoutManager(WX2Activity.this, 3));rvWx2.setAdapter(wxAdapter);wxAdapter.bindToRecyclerView(rvWx2); 復制代碼WxAdapter,這里使用的是 BaseRecyclerViewAdapterHelper
class WxAdapter extends BaseQuickAdapter<String, BaseViewHolder> {public WxAdapter(List<String> list) {super(R.layout.item_wx2, list);}protected void convert(BaseViewHolder helper, String item) {ImageView iv_img = helper.getView(R.id.iv_wx_img);Glide.with(mContext).load(item).apply(new RequestOptions().centerCrop()).into(iv_img);}} 復制代碼item_wx2.xml,請注意這里的指定了transitionName,這個可以自定義,只需和目標view統一即可
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:id="@+id/iv_wx_img"android:layout_width="match_parent"android:transitionName="share"android:layout_height="0dp"app:layout_constraintDimensionRatio="1:1" /></android.support.constraint.ConstraintLayout> 復制代碼當點擊圖片時,我們需要跳轉至查看大圖頁面
wxAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {public void onItemClick(BaseQuickAdapter adapter, View view, int position) {ImageView iv = view.findViewById(R.id.iv_wx_img);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {share(iv, position);}}}); 復制代碼此處的share 需與之前布局保持一致
(api = Build.VERSION_CODES.LOLLIPOP)private void share(View view, int position) {Intent intent = new Intent(WX2Activity.this, Img2Activity.class);intent.putStringArrayListExtra(Img2Activity.IMG_KEY, list);intent.putExtra(Img2Activity.IMG_POSITION, position);Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(this, view, "share").toBundle();startActivity(intent, bundle);} 復制代碼Img2Activity ,這里我們使用RecyclerView+PagerSnapHelper,關于PagerSnapHelper,在之前的文章中,已經說過,這里不再細述。具體可以查看【Android 進階】仿抖音系列之翻頁上下滑切換視頻(四)
private void initView() {imgList = getIntent().getStringArrayListExtra(IMG_KEY);enterPosition = getIntent().getIntExtra(IMG_POSITION, 0);snapHelper = new PagerSnapHelper();snapHelper.attachToRecyclerView(rvPreview);imgAdapter = new ImgAdapter(imgList);rvPreview.setLayoutManager(new LinearLayoutManager(Img2Activity.this, LinearLayoutManager.HORIZONTAL, false));rvPreview.setAdapter(imgAdapter);imgAdapter.bindToRecyclerView(rvPreview);rvPreview.scrollToPosition(enterPosition); } 復制代碼這里,取出之前傳遞的值,并初始化 ImgAdapter
class ImgAdapter extends BaseQuickAdapter<String, BaseViewHolder> {public ImgAdapter(List<String> list) {super(R.layout.item_img, list);}protected void convert(BaseViewHolder helper, String item) {ImageView iv_img = helper.getView(R.id.iv_img);Glide.with(mContext).load(item).into(iv_img);}} 復制代碼item_img,transitionName 需要與之前保持一致,此處PhotoView支持手勢放大,不需要的可以用ImageView代替
xml version="1.0" encoding="utf-8" <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><com.ch.animdemo.phoneView.PhotoViewandroid:id="@+id/iv_img"android:layout_width="0dp"android:layout_height="0dp"android:transitionName="share"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></android.support.constraint.ConstraintLayout> 復制代碼到這里,基本效果已經實現了,不過還有2個坑要填。 1.當我們運行時會發現,會出現Img2Activity出現是小圖,而不是我們期望的大圖。 這是因為,加載網絡圖片需要時間,如果過度動畫執行太快,圖片還沒有加載出來,而glide緩存策略是按加載的尺寸+圖片路徑緩存,由于之前緩存過小圖,所以當大圖沒有加載出來時,會顯示小圖。 所以我們剛進入界面時,需要延遲過度動畫的執行
// 延遲共享動畫的執行postponeEnterTransition(); 復制代碼當圖片加載完成時,才繼續執行過度動畫
//圖片加載完成的回調中,啟動過渡動畫startPostponedEnterTransition(); 復制代碼2.當我們滑動大圖界面,然后返回時會發現,返回動畫依然是進入大圖界面的位置,所以我們需要判斷,如果滑動過,就需要更新返回時的位置。 修改之前Img2Activity的initview方法如下:
private void initView() {// 延遲共享動畫的執行postponeEnterTransition();imgList = getIntent().getStringArrayListExtra(IMG_KEY);enterPosition = getIntent().getIntExtra(IMG_POSITION, 0);currentPosition = enterPosition;snapHelper = new PagerSnapHelper() {public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {currentPosition = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);return currentPosition;}};snapHelper.attachToRecyclerView(rvPreview);imgAdapter = new ImgAdapter(imgList);rvPreview.setLayoutManager(new LinearLayoutManager(Img2Activity.this, LinearLayoutManager.HORIZONTAL, false));rvPreview.setAdapter(imgAdapter);imgAdapter.bindToRecyclerView(rvPreview);rvPreview.scrollToPosition(enterPosition);} 復制代碼finishAfterTransition重寫finishAfterTransition,傳遞最新的position
public void finishAfterTransition() {Intent intent = new Intent();if (enterPosition == currentPosition) {//沒有改變intent.putExtra(IMG_CURRENT_POSITION, -1);} else {intent.putExtra(IMG_CURRENT_POSITION, currentPosition);}setResult(RESULT_OK, intent);super.finishAfterTransition();} 復制代碼然后在WX2Activity中處理
public void onActivityReenter(int resultCode, Intent data) {if (resultCode == RESULT_OK && data != null) {int exitPos = data.getIntExtra(Img2Activity.IMG_CURRENT_POSITION, -1);final View exitView = getExitView(exitPos);if (exitView != null) {ActivityCompat.setExitSharedElementCallback(this, new SharedElementCallback() {public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {names.clear();sharedElements.clear();names.add(ViewCompat.getTransitionName(exitView));sharedElements.put(Objects.requireNonNull(ViewCompat.getTransitionName(exitView)), exitView);setExitSharedElementCallback(new SharedElementCallback() {});}});}}}private View getExitView(int position) {if (position == -1) {return null;}if (wxAdapter != null) {return wxAdapter.getViewByPosition(position, R.id.iv_wx_img);}return null;} 復制代碼最后獻上源碼 github
你的認可,是我堅持更新博客的動力,如果覺得有用,就請點個贊,謝謝
總結
以上是生活随笔為你收集整理的【Android视图效果】共享元素实现仿微信查看大图效果的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 技术面试老是有劲使不出,该怎么办?
- 下一篇: webpackPlugin插件总结