Android 開源項(xiàng)目分析計(jì)劃(一)——Google IO 2016 共享元素過渡動(dòng)畫demo

本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明地址:http://www.itdecent.cn/p/0fd084dd836a


今天要分析的開源項(xiàng)目是: https://github.com/googlesamples/android-unsplash 。這是2016年Google IO大會(huì)上的一個(gè)演示demo。雖然是兩年前的項(xiàng)目了,但還是能發(fā)現(xiàn)一點(diǎn)有用的東西。

效果如下:


2.gif
  1. 我是如何錄制這個(gè)gif的?
adb shell screenrecord  /sdcard/test/1.mp4
adb pull /sdcard/test/1.mp4 .

//去ffmpeg官網(wǎng)下載ffmpeg:
ffmpeg.exe -i 1.mp4  -r 15  -vf fps=15,scale=270:-1  1.gif
(-r: 指定幀率
scale=width:height iw/ih 表示輸入寬度/高度, -1 表示按輸入尺寸等比自動(dòng)計(jì)算)
  1. 項(xiàng)目所使用的依賴庫(kù):
dependencies {
    compile "com.android.support:support-annotations:${supportLibVersion}"
    compile "com.android.support:recyclerview-v7:${supportLibVersion}"
    compile 'com.squareup.retrofit:retrofit:1.9.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

minSdkVersion=21, targetSdkVersion=23

  1. 如何用RecyclerView實(shí)現(xiàn)gif中類似瀑布流的效果?
        RecyclerView grid;
        grid = (RecyclerView) findViewById(R.id.image_grid);
        ...
        GridLayoutManager gridLayoutManager = (GridLayoutManager) grid.getLayoutManager();
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                /* emulating https://material-design.storage.googleapis.com/publish/material_v_4/material_ext_publish/0B6Okdz75tqQsck9lUkgxNVZza1U/style_imagery_integration_scale1.png */
                switch (position % 6) {
                    case 5:
                        return 3;
                    case 3:
                        return 2;
                    default:
                        return 1;
                }
            }
        });
        

其實(shí)就是根據(jù)position修改getSpanSize的返回值,如果spanSize為1,則表示那一張圖片獨(dú)占一行空間。

4.使用了Retrofit來請(qǐng)求 https://unsplash.it/ 的最新圖片:

/**
 * Modeling the unsplash.it API.
 */
public interface UnsplashService {

    String ENDPOINT = "https://unsplash.it";

    @GET("/list")
    void getFeed(Callback<List<Photo>> callback);

}

使用的時(shí)候:

UnsplashService unsplashApi = new RestAdapter.Builder()
                    .setEndpoint(UnsplashService.ENDPOINT)
                    .build()
                    .create(UnsplashService.class);
            unsplashApi.getFeed(new Callback<List<Photo>>() {
                @Override
                public void success(List<Photo> photos, Response response) {
                    // the first items not interesting to us, get the last <n>
                    relevantPhotos = new ArrayList<>(photos.subList(photos.size() - PHOTO_COUNT,
                            photos.size()));
                    populateGrid();
                }

                @Override
                public void failure(RetrofitError error) {
                    Log.e(TAG, "Error retrieving Unsplash feed:", error);
                }
            });
  1. 給RecyclerView添加白邊:
        grid.addItemDecoration(new GridMarginDecoration(
                getResources().getDimensionPixelSize(R.dimen.grid_item_spacing)));//grid_item_spacing的值是2dp
public class GridMarginDecoration extends RecyclerView.ItemDecoration {

    private int space;

    public GridMarginDecoration(int space) {
        this.space = space;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view,
                               RecyclerView parent, RecyclerView.State state) {
        outRect.left = space;
        outRect.top = space;
        outRect.right = space;
        outRect.bottom = space;
    }
}
  1. RecyclerView的點(diǎn)擊事件?
grid.addOnItemTouchListener(new OnItemSelectedListener(MainActivity.this) {
            public void onItemSelected(RecyclerView.ViewHolder holder, int position) {
                 ....
            }
        });

我一直以為RecyclerView沒有類似ListView的OnItemClickListener,原來已經(jīng)有了啊。

  1. 使用了 Data Binding.
    需要在build.gradle里手動(dòng)開啟:
    dataBinding {
        enabled = true
    }

具體使用細(xì)節(jié)不再描述。

  1. 如何實(shí)現(xiàn)共享元素的過渡動(dòng)畫效果?
    涉及的style有:
<style name="App.Home">
        <item name="android:windowExitTransition">@transition/grid_exit</item>
        <item name="android:windowReenterTransition">@transition/grid_reenter</item>
    </style>

    <style name="App.Details">
        <item name="android:windowSharedElementEnterTransition">
            @transition/shared_main_detail
        </item>
    </style>

/res/transition/grid_exit.xml:

<explode />

/res/transition/grid_reenter.xml:

<slide
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:slideEdge="top"
    android:duration="300"
    android:interpolator="@android:interpolator/linear_out_slow_in">
</slide>

/res/transition/shared_main_detail.xml:

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <transitionSet>
        <targets>
            <target android:targetId="@id/photo" />
        </targets>
        <changeBounds>
            <arcMotion android:maximumAngle="50"/>
        </changeBounds>
        <changeTransform />
        <changeClipBounds />
        <changeImageTransform />
    </transitionSet>
    <transitionSet>
        <targets>
            <target android:targetId="@id/author" />
        </targets>
        <transition class="com.example.android.unsplash.transition.TextResize" />
        <changeBounds />
    </transitionSet>
    <recolor>
        <targets>
            <target android:targetId="@android:id/statusBarBackground" />
            <target android:targetId="@android:id/navigationBarBackground" />
        </targets>
    </recolor>
</transitionSet>

涉及的方法有:

postponeEnterTransition();
getWindow().getSharedElementExitTransition().addListener(...);
postponeEnterTransition();

startPostponedEnterTransition();

setExitSharedElementCallback(...);

getWindow().setEnterTransition(...);
setEnterSharedElementCallback(...);

@Override
public void finishAfterTransition() {
    ...
}
@Override
public void onActivityReenter(int resultCode, Intent data) {
    ...
}

具體使用細(xì)節(jié)不再描述。

Over。

本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明地址:http://www.itdecent.cn/p/0fd084dd836a

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容