Răsfoiți Sursa

Added user avatar with collapsing animation

Vadik Sirekanyan 7 ani în urmă
părinte
comite
bf8ef82e8d

+ 2 - 2
app/src/main/java/me/vadik/knigopis/common/ImageView.kt

@@ -6,12 +6,12 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
 import com.bumptech.glide.request.RequestOptions
 import me.vadik.knigopis.R
 
-fun ImageView.setCircleImage(url: String?) {
+fun ImageView.setCircleImage(url: String?, placeholder: Int? = null) {
     Glide.with(context)
         .load(url)
         .apply(
             RequestOptions.circleCropTransform()
-                .placeholder(R.drawable.oval_placeholder_background)
+                .placeholder(placeholder ?: R.drawable.oval_placeholder_background)
         )
         .transition(DrawableTransitionOptions.withCrossFade())
         .into(this)

+ 6 - 0
app/src/main/java/me/vadik/knigopis/extensions.kt

@@ -7,8 +7,10 @@ import android.content.Context
 import android.content.Intent
 import android.net.Uri
 import android.os.Build
+import android.support.annotation.DimenRes
 import android.support.annotation.LayoutRes
 import android.support.annotation.StringRes
+import android.support.v4.view.ViewCompat
 import android.text.Html
 import android.text.Spanned
 import android.util.Log
@@ -94,6 +96,10 @@ fun <T> RequestBuilder<T>.doOnSuccess(onSuccess: () -> Unit): RequestBuilder<T>
         }
     })
 
+fun View.setElevationRes(@DimenRes elevation: Int) {
+    ViewCompat.setElevation(this, resources.getDimensionPixelSize(elevation).toFloat())
+}
+
 fun View.showNow() {
     visibility = View.VISIBLE
 }

+ 4 - 5
app/src/main/java/me/vadik/knigopis/user/UserActivity.kt

@@ -12,18 +12,15 @@ import android.support.v7.widget.LinearLayoutManager
 import android.view.Menu
 import android.view.MenuItem
 import kotlinx.android.synthetic.main.user_activity.*
-import me.vadik.knigopis.R
+import me.vadik.knigopis.*
 import me.vadik.knigopis.adapters.books.BooksAdapter
 import me.vadik.knigopis.adapters.books.UserBook
 import me.vadik.knigopis.api.Endpoint
 import me.vadik.knigopis.auth.KAuth
+import me.vadik.knigopis.common.setCircleImage
 import me.vadik.knigopis.dialog.DialogFactory
-import me.vadik.knigopis.io2main
-import me.vadik.knigopis.logError
 import me.vadik.knigopis.model.note.Identity
 import me.vadik.knigopis.model.subscription.Subscription
-import me.vadik.knigopis.systemClipboardManager
-import me.vadik.knigopis.toast
 import org.koin.android.ext.android.inject
 
 private const val EXTRA_USER_ID = "me.vadik.knigopis.extra_user_id"
@@ -57,6 +54,8 @@ class UserActivity : AppCompatActivity() {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.user_activity)
         toolbar.title = intent.getStringExtra(EXTRA_USER_NAME)
+        toolbarImage.setCircleImage(intent.getStringExtra(EXTRA_USER_PHOTO), R.drawable.oval_dark_placeholder_background)
+        toolbarImage.setElevationRes(R.dimen.image_view_elevation)
         setSupportActionBar(toolbar)
         fab.setOnClickListener { view ->
             fab.hide()

+ 17 - 0
app/src/main/java/me/vadik/knigopis/view/BehaviorHelper.kt

@@ -0,0 +1,17 @@
+package me.vadik.knigopis.view
+
+import android.view.View
+
+val View.simpleState get() = SimpleViewState(x.toInt(), y.toInt(), width, height)
+
+class BehaviorHelper(val start: SimpleViewState, val end: SimpleViewState) {
+
+    fun updateDimensions(child: View, ratio: Float) {
+        val dW = (end.width - start.width) * ratio
+        val dH = (end.height - start.height) * ratio
+        child.scaleX = 1 + dW / start.width
+        child.scaleY = 1 + dH / start.height
+        child.translationX = (end.x - start.x) * ratio + dW / 2
+        child.translationY = (end.y - start.y) * ratio + dH / 2
+    }
+}

+ 50 - 0
app/src/main/java/me/vadik/knigopis/view/SimpleBehavior.kt

@@ -0,0 +1,50 @@
+package me.vadik.knigopis.view
+
+import android.content.Context
+import android.support.design.widget.CoordinatorLayout
+import android.util.AttributeSet
+import android.view.View
+import me.vadik.knigopis.R.styleable.*
+
+class SimpleBehavior(
+    context: Context,
+    attrs: AttributeSet
+) : CoordinatorLayout.Behavior<View>(context, attrs) {
+
+    private val dependViewId: Int
+    private var behaviorHelper: BehaviorHelper? = null
+    private val endState: SimpleViewState
+    private val minHeight: Int
+    private val maxHeight: Int
+
+    init {
+        val a = context.obtainStyledAttributes(attrs, ViewBehavior)
+        dependViewId = a.getResourceId(ViewBehavior_appBarLayout, 0)
+        maxHeight = a.getDimensionPixelOffset(ViewBehavior_appBarMaxHeight, 0)
+        minHeight = a.getDimensionPixelOffset(ViewBehavior_appBarMinHeight, 0)
+        endState = SimpleViewState(
+            a.getDimensionPixelOffset(ViewBehavior_toX, 0),
+            a.getDimensionPixelOffset(ViewBehavior_toY, 0),
+            a.getDimensionPixelOffset(ViewBehavior_toWidth, 0),
+            a.getDimensionPixelOffset(ViewBehavior_toHeight, 0)
+        )
+        a.recycle()
+    }
+
+    override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View) =
+        dependency.id == dependViewId
+
+    override fun onDependentViewChanged(
+        parent: CoordinatorLayout,
+        child: View,
+        dependency: View
+    ): Boolean {
+        behaviorHelper?.let { helper ->
+            val ratio = Math.abs(dependency.y) / (maxHeight - minHeight)
+            helper.updateDimensions(child, Math.min(1f, ratio))
+        } ?: run {
+            behaviorHelper = BehaviorHelper(child.simpleState, endState)
+        }
+        return false
+    }
+}

+ 8 - 0
app/src/main/java/me/vadik/knigopis/view/SimpleViewState.kt

@@ -0,0 +1,8 @@
+package me.vadik.knigopis.view
+
+class SimpleViewState(
+    val x: Int,
+    val y: Int,
+    val width: Int,
+    val height: Int
+)

+ 1 - 1
app/src/main/res/drawable/ic_arrow_back.xml

@@ -4,6 +4,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FF000000"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
 </vector>

+ 1 - 1
app/src/main/res/drawable/ic_done.xml

@@ -4,6 +4,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#FF000000"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
 </vector>

+ 5 - 0
app/src/main/res/drawable/oval_dark_placeholder_background.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="@color/image_placeholder_color_dark" />
+</shape>

+ 1 - 0
app/src/main/res/layout/activity_main.xml

@@ -18,6 +18,7 @@
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            app:popupTheme="@style/ToolbarPopupTheme"
             app:title="@string/app_name" />
 
     </android.support.design.widget.AppBarLayout>

+ 1 - 0
app/src/main/res/layout/book_edit.xml

@@ -17,6 +17,7 @@
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            app:popupTheme="@style/ToolbarPopupTheme"
             tools:title="@string/book_add_title" />
 
     </android.support.design.widget.AppBarLayout>

+ 27 - 7
app/src/main/res/layout/user_activity.xml

@@ -5,36 +5,56 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/white"
-    android:fitsSystemWindows="true"
     tools:context="me.vadik.knigopis.user.UserActivity">
 
     <android.support.design.widget.AppBarLayout
         android:id="@+id/app_bar"
         android:layout_width="match_parent"
-        android:layout_height="180dp"
-        android:fitsSystemWindows="true"
-        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
+        android:layout_height="@dimen/app_bar_height"
+        android:theme="@style/AppBarTheme">
 
         <android.support.design.widget.CollapsingToolbarLayout
             android:id="@+id/toolbar_layout"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:fitsSystemWindows="true"
             app:contentScrim="?attr/colorPrimary"
+            app:expandedTitleGravity="center_vertical"
+            app:expandedTitleMarginBottom="16dp"
+            app:expandedTitleMarginStart="@dimen/title_start_margin_expanded"
+            app:expandedTitleMarginTop="56dp"
             app:layout_scrollFlags="scroll|exitUntilCollapsed"
             app:toolbarId="@+id/toolbar">
 
             <android.support.v7.widget.Toolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
-                android:layout_height="?attr/actionBarSize"
+                android:layout_height="@dimen/toolbar_height"
                 app:layout_collapseMode="pin"
-                app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
+                app:popupTheme="@style/ToolbarPopupTheme"
+                app:titleMarginStart="@dimen/title_start_margin_collapsed" />
 
         </android.support.design.widget.CollapsingToolbarLayout>
 
     </android.support.design.widget.AppBarLayout>
 
+    <ImageView
+        android:id="@+id/toolbarImage"
+        android:layout_width="@dimen/avatar_size_expanded"
+        android:layout_height="@dimen/avatar_size_expanded"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp"
+        android:layout_marginTop="56dp"
+        android:src="@drawable/oval_dark_placeholder_background"
+        app:appBarLayout="@+id/app_bar"
+        app:appBarMaxHeight="@dimen/app_bar_height"
+        app:appBarMinHeight="@dimen/toolbar_height"
+        app:layout_behavior="me.vadik.knigopis.view.SimpleBehavior"
+        app:toHeight="40dp"
+        app:toWidth="40dp"
+        app:toX="64dp"
+        app:toY="8dp"
+        tools:ignore="ContentDescription" />
+
     <android.support.v7.widget.RecyclerView
         android:id="@+id/userBooksRecyclerView"
         android:layout_width="match_parent"

+ 9 - 0
app/src/main/res/values/attrs.xml

@@ -1,4 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <attr name="image_placeholder_color" format="reference|color" />
+    <declare-styleable name="ViewBehavior">
+        <attr name="appBarLayout" format="reference" />
+        <attr name="appBarMaxHeight" format="dimension" />
+        <attr name="appBarMinHeight" format="dimension" />
+        <attr name="toX" format="dimension" />
+        <attr name="toY" format="dimension" />
+        <attr name="toWidth" format="dimension" />
+        <attr name="toHeight" format="dimension" />
+    </declare-styleable>
 </resources>

+ 11 - 0
app/src/main/res/values/dimens.xml

@@ -1,4 +1,15 @@
 <resources>
+
+    <!-- common -->
     <dimen name="activity_horizontal_margin">16dp</dimen>
     <dimen name="activity_vertical_margin">16dp</dimen>
+
+    <!-- user avatar -->
+    <dimen name="avatar_size_expanded">88dp</dimen>
+    <dimen name="toolbar_height">56dp</dimen>
+    <dimen name="app_bar_height">160dp</dimen>
+    <dimen name="title_start_margin_expanded">120dp</dimen>
+    <dimen name="title_start_margin_collapsed">48dp</dimen>
+    <dimen name="image_view_elevation">4dp</dimen>
+
 </resources>

+ 3 - 7
app/src/main/res/values/styles.xml

@@ -23,13 +23,9 @@
         <!--<item name="colorPrimaryDark">#7B1FA2</item>-->
     </style>
 
-    <style name="AppBarTheme">
-        <item name="actionMenuTextColor">@color/white</item>
-        <item name="titleTextColor">@color/white</item>
-        <item name="android:textColorSecondary">@color/white</item>
-        <item name="iconTint">@color/white</item>
-        <item name="android:tint">@color/white</item>
-    </style>
+    <style name="AppBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+    <style name="ToolbarPopupTheme" parent="@style/ThemeOverlay.AppCompat.Light" />
 
     <style name="AboutItem">
         <item name="android:layout_height">wrap_content</item>