[컴][안드로이드] CollapsedToolbar 에서 alphaed 배경이미지 넣기

새로운 툴바에서 스크롤할 때 메인에 있던 이미지를 툴바에 넣고 싶다. / blurred image on toolbar / 툴바에 투명한 이미지 넣기 / app bar 아래에 view 를 고정할 때 / fixed view below the app bar / header below the app bar




CoordinatorLayout 에서 toolbar 를 scroll 할 때 좀 더 정교하게 다루는데 사용되는 것이 CollapsingToolbarLayout 인데, 자세한 사항은 ref.1 이나 ref. 2 를 보자.

여하튼 여기서는 CollapsingToolbarLayout 를 이용해서 scroll 해서 화면이 위로 올라갔을 때 최상단에 있던 이미지가 toolbar 에 alpha 가 적용된 상태로 보여지게 할 것이다.


Toolbar 에 alpha 가 적용된 이미지 사용방법

Android template 으로 제공하는 ScrollingActivity 를 기본으로 설명하려 한다. 소스의 변경사항은 아래와 같다.

대략적인 사용법은 간단하다. 아래 2가지면 된다.
  1. xml 변경 : xml 에 기본적으로 app:contentScrim="?attr/colorPrimary" 설정이 되어있는데 이것을 없애자. 그래야 toolbar 의 background 로 image view 의 그림이 설정된다.
  2. AppBarLayout.OnOffsetChangedListener 추가 : change-listener 를 appbar 에 추가해줘야 한다. 이녀석을 추가해서 toolbar 가 collapsed 되었을 때 alpha 값을 주게 할 수 있다.

xml 변경사항

xml 변경사항의 자세한 부분은 위의 "변경사항 diff" 를 확인하자.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 
    ...>

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        ...>

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                ... />



        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_scrolling" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        ... />

</android.support.design.widget.CoordinatorLayout>


OnOffsetChangedListener

OnOffsetChangedListener 에 대한 source code 는 아래 경로를 참고했다.

이녀석을 통해서 toolbar 에 collapsed 됐을 때 toolbar 의 image 를 투명하게 할 수 있다.
public class ScrollingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        loadBackdrop();
    }

    private void loadBackdrop() {
        final CollapsingToolbarLayout collapsingToolbar =
                (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbar.setTitle("My New Title");

        final int myDrawable = R.drawable.cheese_1;
        final ImageView iv = (ImageView)findViewById(R.id.backdrop);
        if (iv != null) {
            iv.setImageResource(myDrawable);
        }


        AppBarLayout.OnOffsetChangedListener listener = new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if(collapsingToolbar.getHeight() + verticalOffset < 2 * ViewCompat.getMinimumHeight(collapsingToolbar)) {
                    // collapsed
                    iv.animate().alpha(0.3f).setDuration(600);
                } else {
                    // extended
                    iv.animate().alpha(1f).setDuration(600);    // 1.0f means opaque
                }
            }
        };

        final AppBarLayout appbar = (AppBarLayout) findViewById(R.id.appbar);
        appbar.addOnOffsetChangedListener(listener);
    }

   ...
}


toolbar(appbar) 의 그림자 없애기

app:elevation="0dp" 로 없앨 수 있다.


<android.support.design.widget.CoordinatorLayout 
    ...>
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
         ...
        app:elevation="0dp">


collapsed toolbar 의 배경 지정하기

추가적으로 collapsed toolbar layout 에 배경(색, 이미지)에 대한 이야기를 해보자.

기본적으로 CollapsingToolbarLayout 에 app:contentScrim 를 정해주지 않으면, ImageView 의 그림이 그대로 들어가 있게 된다. 이 배경은 contentScrim 으로 지정해 줄 수 있다.

primary color 로

이 상황에서 collaped 됐을 때 primaryColor 로 바꾸고 싶다면 아래처럼 설정해주면 된다.
  • app:contentScrim="?attr/colorPrimary"


blurred image 로 배경이미지 넣기

이 방법은 alpha 로 넣는 방법을 발견하기 전에 하던 방법인데, imageView 에서 사용된 image 를 가져다가 blurred image 로 만들어서 그녀석을 collapsed toolbar 의 scrim 으로 설정해 줬다.

Blurred image 는 code 로 넣어야 한다. 일단 view 가 호출될 때
onCreate() 에 ImageView 에 사용되는 image 의 drawable 의 blurred 해서
이 녀석을 CollapsingToolbarLayout 의 contentScrim 으로 지정해 주면 된다.
final Drawable d = new BitmapDrawable(getResources(), CreateBlurredImage(cheeseDrawable, 20));
collapsingToolbar.setContentScrim(d);

CreateBlurredImage 는 ref. 1 의 소스를 참고했다.
private Bitmap CreateBlurredImage (int imageId, int radius)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return BitmapFactory.decodeResource(getResources(), imageId);
        }

        // Load a clean bitmap and work from that.
        Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), imageId);

        // Create another bitmap that will hold the results of the filter.
        Bitmap blurredBitmap;
        blurredBitmap = Bitmap.createBitmap(originalBitmap);

        // Create the Renderscript instance that will do the work.
        RenderScript rs = RenderScript.create(this);

        // Allocate memory for Renderscript to work with
        Allocation input = Allocation.createFromBitmap(
                rs, originalBitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SCRIPT);
        Allocation output = Allocation.createTyped(rs, input.getType());

        // Load up an instance of the specific script that we want to use.
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
        script.setInput(input);

        // Set the blur radius
        script.setRadius(radius);

        // Start the ScriptIntrinisicBlur
        script.forEach(output);

        // Copy the output to the blurred bitmap
        output.copyTo(blurredBitmap);

        return blurredBitmap;
    }













Toolbar(Appbar) 아래에 view 를 고정시킬 경우

이 경우는 scroll 이 되는 view 를 appbar 밖으로 놓고, scroll 되는 녀석이랑 같은 level 로 놓으면 된다.(아래 코드 참조)


<android.support.design.widget.CoordinatorLayout
    ...>

    <android.support.design.widget.AppBarLayout
        ...>

        <android.support.design.widget.CollapsingToolbarLayout
            ...>
            
            ...

            <android.support.v7.widget.Toolbar
                ... />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        ...
        android:orientation="vertical">


        <TextView
            ...

            android:textIsSelectable="true" />


        <android.support.v4.widget.NestedScrollView
            android:id="@+id/nsv_activity"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
            ...


        </android.support.v4.widget.NestedScrollView>
    </LinearLayout>

    <android.support.design.widget.FloatingActionButton
        ..."/>

</android.support.design.widget.CoordinatorLayout>





See Also

  1. CoordinatorLayout 을 위한 Custom Behavior 구현 | README
  2. Android Design Support Library | Android Developers Blog > Collapsing Toolbars

댓글 6개:

  1. 궁금한게 있는데요
    final Drawable d = new BitmapDrawable(getResources(), CreateBlurredImage(cheeseDrawable, 20));
    collapsingToolbar.setContentScrim(d); 여기서 cheeseDrawable 이 먼가요?

    답글삭제
  2. 그냥 drawable 를 변수로 받은 것입니다. 소스를 붙여넣다보니, 그리됐네요 ^^;; 그냥 아무 drawable 이나 대신 사용하시면 될 것입니다.

    답글삭제
  3. 좋은글 감사합니다

    답글삭제
  4. 도움이 많이 되었습니다 감사드립니다.

    답글삭제
    답글
    1. 네, 저도 읽어주셔서 감사~

      삭제