diff --git a/twidere/src/androidTest/kotlin/org/mariotaku/twidere/extension/ViewExtensionsKtTest.kt b/twidere/src/androidTest/kotlin/org/mariotaku/twidere/extension/ViewExtensionsKtTest.kt new file mode 100644 index 000000000..6dc426088 --- /dev/null +++ b/twidere/src/androidTest/kotlin/org/mariotaku/twidere/extension/ViewExtensionsKtTest.kt @@ -0,0 +1,31 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.extension + +import android.support.test.runner.AndroidJUnit4 +import org.junit.runner.RunWith + +/** + * Created by mariotaku on 2017/2/20. + */ +@RunWith(AndroidJUnit4::class) +class ViewExtensionsKtTest { + +} \ No newline at end of file diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/ShapedImageView.java b/twidere/src/main/java/org/mariotaku/twidere/view/ShapedImageView.java index 4f2191b59..dd7f6ffdb 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/ShapedImageView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/ShapedImageView.java @@ -81,6 +81,7 @@ public class ShapedImageView extends ImageView { private float mShadowRadius; private int mStyle; private float mCornerRadius, mCornerRadiusRatio; + private boolean mDrawShadow; private RectF mTransitionSource, mTransitionDestination; private int mStrokeWidth, mBorderAlpha; private int[] mBorderColors; @@ -126,6 +127,7 @@ public class ShapedImageView extends ImageView { setStyle(shapeStyle); setCornerRadius(a.getDimension(R.styleable.ShapedImageView_sivCornerRadius, 0)); setCornerRadiusRatio(a.getFraction(R.styleable.ShapedImageView_sivCornerRadiusRatio, 1, 1, -1)); + setDrawShadow(a.getBoolean(R.styleable.ShapedImageView_sivDrawShadow, true)); if (useOutline()) { if (a.hasValue(R.styleable.ShapedImageView_sivElevation)) { @@ -151,7 +153,7 @@ public class ShapedImageView extends ImageView { * @param dest The destination bound on the canvas. */ public void drawBitmapWithCircleOnCanvas(Bitmap bitmap, Canvas canvas, - RectF source, @NonNull RectF dest) { + RectF source, @NonNull RectF dest) { if (bitmap == null) { if (getStyle() == SHAPE_CIRCLE) { canvas.drawCircle(dest.centerX(), dest.centerY(), Math.min(dest.width(), dest.height()) / 2f, @@ -265,6 +267,10 @@ public class ShapedImageView extends ImageView { mCornerRadiusRatio = ratio; } + public void setDrawShadow(final boolean drawShadow) { + mDrawShadow = drawShadow; + } + public void setTransitionDestination(RectF dstBounds) { mTransitionDestination = dstBounds; } @@ -423,7 +429,7 @@ public class ShapedImageView extends ImageView { private void initOutlineProvider() { if (!useOutline()) return; ViewSupport.setClipToOutline(this, true); - ViewSupport.setOutlineProvider(this, new CircularOutlineProvider()); + ViewSupport.setOutlineProvider(this, new CircularOutlineProvider(mDrawShadow)); } private void setBorderColorsInternal(int alpha, int... colors) { @@ -504,6 +510,12 @@ public class ShapedImageView extends ImageView { } private static class CircularOutlineProvider extends ViewOutlineProviderCompat { + boolean drawShadow; + + public CircularOutlineProvider(final boolean drawShadow) { + this.drawShadow = drawShadow; + } + @Override public void getOutline(View view, OutlineCompat outline) { final int viewWidth = view.getWidth(), viewHeight = view.getHeight(); @@ -523,6 +535,11 @@ public class ShapedImageView extends ImageView { final float radius = imageView.getCalculatedCornerRadius(); outline.setRoundRect(contentLeft, contentTop, contentRight, contentBottom, radius); } + if (drawShadow) { + outline.setAlpha(1); + } else { + outline.setAlpha(0); + } } } } \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.kt index 7609eb404..2a1f5fbba 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/adapter/SimpleParcelableUserListsAdapter.kt @@ -26,7 +26,7 @@ import org.mariotaku.twidere.R import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter import org.mariotaku.twidere.model.ItemCounts import org.mariotaku.twidere.model.ParcelableUserList -import org.mariotaku.twidere.util.view.display +import org.mariotaku.twidere.extension.view.holder.display import org.mariotaku.twidere.view.holder.SimpleUserListViewHolder class SimpleParcelableUserListsAdapter( diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/RectExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/RectExtensions.kt new file mode 100644 index 000000000..fc05e96dd --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/RectExtensions.kt @@ -0,0 +1,29 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.extension + +import android.graphics.Point +import android.graphics.Rect + +/** + * Created by mariotaku on 2017/2/20. + */ + +val Rect.origin: Point get() = Point(left, top) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt new file mode 100644 index 000000000..983f208eb --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt @@ -0,0 +1,69 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.extension + +import android.graphics.Rect +import android.graphics.RectF +import android.support.annotation.MainThread +import android.view.View + +private val tempLocation = IntArray(2) +private val tempRect = Rect() + +@MainThread +fun View.getBounds(rect: RectF) { + rect.set(x, y, x + width, y + height) +} + +@MainThread +fun View.getFrame(rect: Rect) { + rect.set(left, top, right, bottom) +} + +@MainThread +fun View.getFrameRelatedTo(rect: Rect, view: View? = null) { + if (view != null) { + view.getFrame(tempRect) + offsetToRoot(view, tempRect) + } + this.getFrame(rect) + offsetToRoot(this, rect) + if (view != null) { + rect.offset(-tempRect.left, -tempRect.top) + } +} + +fun View.getLocationOnScreen(rect: Rect) { + getLocationOnScreen(tempLocation) + rect.set(tempLocation[0], tempLocation[1], tempLocation[0] + width, tempLocation[1] + height) +} + +fun View.getLocationInWindow(rect: Rect) { + getLocationInWindow(tempLocation) + rect.set(tempLocation[0], tempLocation[1], tempLocation[0] + width, tempLocation[1] + height) +} + +private fun offsetToRoot(view: View, rect: Rect) { + var parent = view.parent as? View + while (parent != null) { + rect.offset(parent.left, parent.top) + parent = parent.parent as? View + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/view/holder/SimpleUserListViewHolderExtension.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/view/holder/SimpleUserListViewHolderExtension.kt new file mode 100644 index 000000000..03bab340e --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/view/holder/SimpleUserListViewHolderExtension.kt @@ -0,0 +1,40 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.extension.view.holder + +import android.view.View +import org.mariotaku.twidere.R +import org.mariotaku.twidere.model.ParcelableUserList +import org.mariotaku.twidere.util.MediaLoaderWrapper +import org.mariotaku.twidere.util.UserColorNameManager +import org.mariotaku.twidere.view.holder.SimpleUserListViewHolder + +fun SimpleUserListViewHolder.display(userList: ParcelableUserList, mediaLoader: MediaLoaderWrapper, + userColorNameManager: UserColorNameManager, displayProfileImage: Boolean) { + nameView.text = userList.name + createdByView.text = createdByView.context.getString(R.string.created_by, + userColorNameManager.getDisplayName(userList, false)) + profileImageView.visibility = if (displayProfileImage) View.VISIBLE else View.GONE + if (displayProfileImage) { + mediaLoader.displayProfileImage(profileImageView, userList) + } else { + mediaLoader.cancelDisplayTask(profileImageView) + } +} \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt index e78554632..208f846f7 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsActivitiesFragment.kt @@ -40,7 +40,6 @@ import org.mariotaku.ktextension.coerceInOr import org.mariotaku.ktextension.isNullOrEmpty import org.mariotaku.ktextension.rangeOfSize import org.mariotaku.twidere.R -import org.mariotaku.twidere.TwidereConstants import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_VIEW_TYPE_GAP import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter.Companion.ITEM_VIEW_TYPE_STATUS @@ -193,7 +192,7 @@ abstract class AbsActivitiesFragment protected constructor() : } override fun handleKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler, keyCode: Int, repeatCount: Int, - event: KeyEvent, metaState: Int): Boolean { + event: KeyEvent, metaState: Int): Boolean { return navigationHelper.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event, metaState) } @@ -305,7 +304,7 @@ abstract class AbsActivitiesFragment protected constructor() : override fun onGapClick(holder: GapViewHolder, position: Int) { val activity = adapter.getActivity(position) ?: return - DebugLog.v(TwidereConstants.LOGTAG, "Load activity gap $activity") + DebugLog.v(msg = "Load activity gap $activity") val accountIds = arrayOf(activity.account_key) val maxIds = arrayOf(activity.min_position) val maxSortIds = longArrayOf(activity.min_sort_position) @@ -451,7 +450,7 @@ abstract class AbsActivitiesFragment protected constructor() : protected abstract fun hasMoreData(data: List?): Boolean protected abstract fun onCreateActivitiesLoader(context: Context, args: Bundle, - fromUser: Boolean): Loader> + fromUser: Boolean): Loader> protected abstract fun onContentLoaded(loader: Loader>, data: List?) @@ -525,7 +524,7 @@ abstract class AbsActivitiesFragment protected constructor() : override fun createItemDecoration(context: Context, recyclerView: RecyclerView, - layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? { + layoutManager: LinearLayoutManager): RecyclerView.ItemDecoration? { val itemDecoration = object : DividerItemDecoration(context, (recyclerView.layoutManager as LinearLayoutManager).orientation) { override fun isDividerEnabled(childPos: Int): Boolean { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsStatusesFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsStatusesFragment.kt index a38118de3..6456297ea 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsStatusesFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AbsStatusesFragment.kt @@ -39,7 +39,6 @@ import kotlinx.android.synthetic.main.fragment_content_recyclerview.* import org.mariotaku.kpreferences.get import org.mariotaku.ktextension.* import org.mariotaku.twidere.R -import org.mariotaku.twidere.TwidereConstants import org.mariotaku.twidere.activity.AccountSelectorActivity import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration @@ -353,7 +352,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment(status.id) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt index a63db9011..7185d4b2c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessageConversationInfoFragment.kt @@ -19,29 +19,79 @@ package org.mariotaku.twidere.fragment.message +import android.content.Context import android.os.Bundle import android.support.v4.app.FragmentActivity +import android.support.v4.app.LoaderManager +import android.support.v4.content.AsyncTaskLoader +import android.support.v4.content.Loader +import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import kotlinx.android.synthetic.main.activity_home_content.view.* import kotlinx.android.synthetic.main.fragment_messages_conversation_info.* +import kotlinx.android.synthetic.main.layout_toolbar_message_conversation_title.* +import org.mariotaku.chameleon.Chameleon +import org.mariotaku.chameleon.ChameleonUtils +import org.mariotaku.kpreferences.get +import org.mariotaku.ktextension.useCursor +import org.mariotaku.sqliteqb.library.Expression import org.mariotaku.twidere.R +import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY +import org.mariotaku.twidere.constant.IntentConstants.EXTRA_CONVERSATION_ID +import org.mariotaku.twidere.constant.nameFirstKey +import org.mariotaku.twidere.constant.profileImageStyleKey +import org.mariotaku.twidere.extension.model.displayAvatarTo +import org.mariotaku.twidere.extension.model.getConversationName import org.mariotaku.twidere.fragment.BaseFragment import org.mariotaku.twidere.fragment.iface.IToolBarSupportFragment +import org.mariotaku.twidere.model.ParcelableMessageConversation +import org.mariotaku.twidere.model.ParcelableMessageConversationCursorIndices +import org.mariotaku.twidere.model.UserKey +import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations /** * Created by mariotaku on 2017/2/15. */ -class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment { +class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment, + LoaderManager.LoaderCallbacks { + + private val accountKey: UserKey get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY) + private val conversationId: String get() = arguments.getString(EXTRA_CONVERSATION_ID) + override val controlBarHeight: Int get() = toolbar.measuredHeight override var controlBarOffset: Float = 0f override val toolbar: Toolbar get() = toolbarLayout.toolbar + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + val activity = this.activity + + if (activity is AppCompatActivity) { + activity.supportActionBar?.setDisplayShowTitleEnabled(false) + } + + val theme = Chameleon.getOverrideTheme(context, activity) + + val profileImageStyle = preferences[profileImageStyleKey] + appBarConversationAvatar.style = profileImageStyle + conversationAvatar.style = profileImageStyle + + val avatarBackground = ChameleonUtils.getColorDependent(theme.colorToolbar) + appBarConversationAvatar.setBackgroundColor(avatarBackground) + appBarConversationName.setTextColor(ChameleonUtils.getColorDependent(theme.colorToolbar)) + + conversationAvatar.setBackgroundColor(avatarBackground) + conversationName.setTextColor(ChameleonUtils.getColorDependent(theme.colorToolbar)) + + loaderManager.initLoader(0, null, this) + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return inflater.inflate(R.layout.fragment_messages_conversation_info, container, false) } @@ -49,4 +99,45 @@ class MessageConversationInfoFragment : BaseFragment(), IToolBarSupportFragment override fun setupWindow(activity: FragmentActivity): Boolean { return false } + + override fun onCreateLoader(id: Int, args: Bundle?): Loader { + return ConversationInfoLoader(context, accountKey, conversationId) + } + + override fun onLoaderReset(loader: Loader?) { + } + + override fun onLoadFinished(loader: Loader?, data: ParcelableMessageConversation?) { + if (data == null) { + activity?.finish() + return + } + val name = data.getConversationName(context, userColorNameManager, preferences[nameFirstKey]).first + data.displayAvatarTo(mediaLoader, conversationAvatar) + data.displayAvatarTo(mediaLoader, appBarConversationAvatar) + appBarConversationName.text = name + conversationName.text = name + } + + class ConversationInfoLoader( + context: Context, + val accountKey: UserKey, + val conversationId: String) : AsyncTaskLoader(context) { + override fun loadInBackground(): ParcelableMessageConversation? { + val where = Expression.and(Expression.equalsArgs(Conversations.ACCOUNT_KEY), + Expression.equalsArgs(Conversations.CONVERSATION_ID)).sql + val whereArgs = arrayOf(accountKey.toString(), conversationId) + context.contentResolver.query(Conversations.CONTENT_URI, Conversations.COLUMNS, where, + whereArgs, null).useCursor { cur -> + if (cur.moveToFirst()) { + return ParcelableMessageConversationCursorIndices.fromCursor(cur) + } + } + return null + } + + override fun onStartLoading() { + forceLoad() + } + } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt index 36f48d047..7a1fbe7a1 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/message/MessagesConversationFragment.kt @@ -163,6 +163,10 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment { - val intent = IntentUtils.messageConversationInfo(accountKey, conversationId) - startActivity(intent) - return true - } } return false } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/conf/UserListExtraConfiguration.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/conf/UserListExtraConfiguration.kt index 790817d28..96cf51088 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/conf/UserListExtraConfiguration.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/conf/UserListExtraConfiguration.kt @@ -15,7 +15,7 @@ import org.mariotaku.twidere.fragment.CustomTabsFragment.TabEditorDialogFragment import org.mariotaku.twidere.model.ParcelableUserList import org.mariotaku.twidere.model.tab.TabConfiguration import org.mariotaku.twidere.util.dagger.DependencyHolder -import org.mariotaku.twidere.util.view.display +import org.mariotaku.twidere.extension.view.holder.display import org.mariotaku.twidere.view.holder.SimpleUserListViewHolder /** diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DebugLog.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DebugLog.kt index 444aa7423..bc0abe740 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/DebugLog.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/DebugLog.kt @@ -2,6 +2,7 @@ package org.mariotaku.twidere.util import android.util.Log import org.mariotaku.twidere.BuildConfig +import org.mariotaku.twidere.TwidereConstants.LOGTAG /** * Created by mariotaku on 2017/1/24. @@ -9,7 +10,7 @@ import org.mariotaku.twidere.BuildConfig object DebugLog { @JvmStatic - fun v(tag: String, msg: String, tr: Throwable? = null): Int { + fun v(tag: String = LOGTAG, msg: String, tr: Throwable? = null): Int { if (!BuildConfig.DEBUG) return 0 if (tr != null) { return Log.v(tag, msg, tr) @@ -19,7 +20,7 @@ object DebugLog { } @JvmStatic - fun d(tag: String, msg: String, tr: Throwable? = null): Int { + fun d(tag: String = LOGTAG, msg: String, tr: Throwable? = null): Int { if (!BuildConfig.DEBUG) return 0 if (tr != null) { return Log.d(tag, msg, tr) @@ -29,7 +30,7 @@ object DebugLog { } @JvmStatic - fun w(tag: String, msg: String? = null, tr: Throwable? = null): Int { + fun w(tag: String = LOGTAG, msg: String? = null, tr: Throwable? = null): Int { if (!BuildConfig.DEBUG) return 0 if (msg != null && tr != null) { return Log.w(tag, msg, tr) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoAvatarBehavior.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoAvatarBehavior.kt new file mode 100644 index 000000000..b08813d5c --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoAvatarBehavior.kt @@ -0,0 +1,122 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.util.view + +import android.content.Context +import android.graphics.Rect +import android.support.design.widget.AppBarLayout +import android.support.design.widget.CoordinatorLayout +import android.support.v4.view.ViewCompat +import android.util.AttributeSet +import android.view.View +import kotlinx.android.synthetic.main.fragment_messages_conversation_info.view.* +import kotlinx.android.synthetic.main.layout_toolbar_message_conversation_title.view.* +import org.mariotaku.twidere.R +import org.mariotaku.twidere.extension.getFrame +import org.mariotaku.twidere.extension.getFrameRelatedTo +import org.mariotaku.twidere.extension.getLocationOnScreen +import org.mariotaku.twidere.extension.origin + +/** + * Created by mariotaku on 2017/2/20. + */ + +class ConversationInfoAvatarBehavior( + context: Context, + attrs: AttributeSet? = null +) : CoordinatorLayout.Behavior(context, attrs) { + private val marginBottom: Float + private val marginStart: Float + + private val appBarRect = Rect() + + private val sourceRect = Rect() + private val destRect = Rect() + private val tempRect = Rect() + + private var toolbarLayoutHeight = 0f + + var dependentPercent: Float = 0f + private set + + init { + val a = context.obtainStyledAttributes(attrs, R.styleable.ConversationInfoAvatarBehavior) + marginBottom = a.getDimension(R.styleable.ConversationInfoAvatarBehavior_behavior_avatarMarginBottom, 0f) + marginStart = a.getDimension(R.styleable.ConversationInfoAvatarBehavior_behavior_avatarMarginStart, 0f) + a.recycle() + } + + override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + return dependency is AppBarLayout + } + + override fun onLayoutChild(parent: CoordinatorLayout, child: View, layoutDirection: Int): Boolean { + val appBar = parent.getDependencies(child).first() + // Get AppBar frame (and reset origin to 0, 0) + appBar.getFrame(appBarRect) + val dependencyOrigin = appBarRect.origin + appBarRect.offsetTo(0, 0) + + // Layout avatar + val left: Int + val right: Int + if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { + right = appBarRect.right - Math.round(marginStart) + left = right - child.measuredWidth + } else { + left = Math.round(marginStart) + right = left + child.measuredWidth + } + val bottom = Math.round(appBarRect.bottom - marginBottom) + val top = bottom - child.measuredHeight + child.layout(left, top, right, bottom) + + + val toolbarLayout = appBar.toolbarLayout + toolbarLayoutHeight = toolbarLayout.height.toFloat() + + child.getFrameRelatedTo(sourceRect) + appBar.conversationAvatar.getFrameRelatedTo(destRect) + return true + } + + override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + val behavior = (dependency.layoutParams as CoordinatorLayout.LayoutParams).behavior as AppBarLayout.Behavior + val toolbar = dependency.toolbar + toolbar.getLocationOnScreen(tempRect) + val percent = behavior.topAndBottomOffset / (tempRect.bottom - toolbarLayoutHeight) + child.pivotX = child.width.toFloat() + child.pivotY = child.height.toFloat() + child.scaleX = 1 - (sourceRect.width() - destRect.width()) * percent / sourceRect.width() + child.scaleY = 1 - (sourceRect.height() - destRect.height()) * percent / sourceRect.height() + child.translationX = (destRect.right - sourceRect.right) * percent + child.translationY = (destRect.bottom - sourceRect.bottom) * percent + + if (percent >= 1) { + child.visibility = View.INVISIBLE + dependency.conversationAvatar.visibility = View.VISIBLE + } else { + child.visibility = View.VISIBLE + dependency.conversationAvatar.visibility = View.INVISIBLE + } + dependentPercent = percent + return true + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoTitleBehavior.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoTitleBehavior.kt new file mode 100644 index 000000000..1888b6918 --- /dev/null +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/ConversationInfoTitleBehavior.kt @@ -0,0 +1,107 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright (C) 2012-2017 Mariotaku Lee + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.mariotaku.twidere.util.view + +import android.content.Context +import android.graphics.Rect +import android.support.design.widget.CoordinatorLayout +import android.support.v4.view.ViewCompat +import android.util.AttributeSet +import android.util.TypedValue +import android.view.View +import android.widget.TextView +import kotlinx.android.synthetic.main.layout_toolbar_message_conversation_title.view.* +import org.mariotaku.twidere.R +import org.mariotaku.twidere.extension.getFrame +import org.mariotaku.twidere.extension.getFrameRelatedTo + +/** + * Created by mariotaku on 2017/2/20. + */ + +class ConversationInfoTitleBehavior( + context: Context, + attrs: AttributeSet? = null +) : CoordinatorLayout.Behavior(context, attrs) { + private val marginBottom: Float + private val marginStart: Float + + private val avatarRect = Rect() + + private val sourceRect = Rect() + private val destRect = Rect() + + private var sourceSize: Float = Float.NaN + private var destSize: Float = Float.NaN + private var viewLaidOut: Boolean = false + + init { + val a = context.obtainStyledAttributes(attrs, R.styleable.ConversationInfoTitleBehavior) + marginBottom = a.getDimension(R.styleable.ConversationInfoTitleBehavior_behavior_titleMarginBottom, 0f) + marginStart = a.getDimension(R.styleable.ConversationInfoTitleBehavior_behavior_titleMarginStart, 0f) + a.recycle() + } + + override fun layoutDependsOn(parent: CoordinatorLayout, child: TextView, dependency: View): Boolean { + return dependency.id == R.id.appBarConversationAvatar + } + + override fun onLayoutChild(parent: CoordinatorLayout, child: TextView, layoutDirection: Int): Boolean { + val conversationAvatar = parent.getDependencies(child).first() + val appBar = conversationAvatar.parent as View + conversationAvatar.getFrame(avatarRect) + if (!viewLaidOut) { + sourceSize = child.textSize + destSize = parent.conversationName.textSize + viewLaidOut = true + } + if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) { + child.right = Math.round(avatarRect.left - marginStart) + child.left = child.right - child.measuredWidth + } else { + child.left = Math.round(avatarRect.right + marginStart) + child.right = child.left + child.measuredWidth + } + child.bottom = Math.round(avatarRect.centerY() - marginBottom) + child.top = child.bottom - child.measuredHeight + + child.getFrameRelatedTo(sourceRect) + appBar.conversationName.getFrameRelatedTo(destRect) + return true + } + + override fun onDependentViewChanged(parent: CoordinatorLayout, child: TextView, dependency: View): Boolean { + val behavior = (dependency.layoutParams as CoordinatorLayout.LayoutParams).behavior as ConversationInfoAvatarBehavior + val percent = behavior.dependentPercent + child.pivotX = child.width.toFloat() + child.pivotY = child.height.toFloat() + child.translationX = (destRect.left - sourceRect.left) * percent + child.translationY = (destRect.top - sourceRect.top) * percent + child.setTextSize(TypedValue.COMPLEX_UNIT_PX, sourceSize + (destSize - sourceSize) * percent) + if (percent >= 1) { + child.visibility = View.INVISIBLE + parent.conversationName.visibility = View.VISIBLE + } else { + child.visibility = View.VISIBLE + parent.conversationName.visibility = View.INVISIBLE + } + return true + } +} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/SimpleUserListViewHolder.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/SimpleUserListViewHolder.kt deleted file mode 100644 index efae21947..000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/view/SimpleUserListViewHolder.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.mariotaku.twidere.util.view - -import android.view.View -import org.mariotaku.twidere.R -import org.mariotaku.twidere.model.ParcelableUserList -import org.mariotaku.twidere.util.MediaLoaderWrapper -import org.mariotaku.twidere.util.UserColorNameManager -import org.mariotaku.twidere.view.holder.SimpleUserListViewHolder - -fun SimpleUserListViewHolder.display(userList: ParcelableUserList, mediaLoader: MediaLoaderWrapper, - userColorNameManager: UserColorNameManager, - displayProfileImage: Boolean) { - nameView.text = userList.name - createdByView.text = createdByView.context.getString(R.string.created_by, - userColorNameManager.getDisplayName(userList, false)) - profileImageView.visibility = if (displayProfileImage) View.VISIBLE else View.GONE - if (displayProfileImage) { - mediaLoader.displayProfileImage(profileImageView, userList) - } else { - mediaLoader.cancelDisplayTask(profileImageView) - } -} \ No newline at end of file diff --git a/twidere/src/main/res/layout/fragment_messages_conversation.xml b/twidere/src/main/res/layout/fragment_messages_conversation.xml index baa149940..7ee8a67d5 100644 --- a/twidere/src/main/res/layout/fragment_messages_conversation.xml +++ b/twidere/src/main/res/layout/fragment_messages_conversation.xml @@ -167,6 +167,7 @@ android:background="?colorToolbar" android:elevation="@dimen/toolbar_elevation" app:contentInsetStart="0dp" + app:contentInsetStartWithNavigation="0dp" app:popupTheme="?actionBarPopupTheme" tools:elevation="0dp"> diff --git a/twidere/src/main/res/layout/fragment_messages_conversation_info.xml b/twidere/src/main/res/layout/fragment_messages_conversation_info.xml index e803eaf72..757b00b0c 100644 --- a/twidere/src/main/res/layout/fragment_messages_conversation_info.xml +++ b/twidere/src/main/res/layout/fragment_messages_conversation_info.xml @@ -10,7 +10,8 @@ + app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:titleEnabled="false"> + android:background="?colorToolbar" + app:contentInsetStart="0dp" + app:contentInsetStartWithNavigation="0dp" + app:layout_collapseMode="pin"> + + + + @@ -48,8 +58,42 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/element_spacing_large" android:src="@drawable/ic_action_edit" + app:backgroundTint="?android:colorBackground" app:layout_anchor="@+id/appBar" app:layout_anchorGravity="bottom|end" - tools:backgroundTint="?colorAccent"/> + tools:tint="?android:colorForeground"/> + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/layout_toolbar_message_conversation_title.xml b/twidere/src/main/res/layout/layout_toolbar_message_conversation_title.xml index f894a69c2..5a79c46cc 100644 --- a/twidere/src/main/res/layout/layout_toolbar_message_conversation_title.xml +++ b/twidere/src/main/res/layout/layout_toolbar_message_conversation_title.xml @@ -21,6 +21,7 @@ + android:gravity="center_vertical" + android:orientation="vertical"> + + \ No newline at end of file diff --git a/twidere/src/main/res/menu/menu_messages_conversation.xml b/twidere/src/main/res/menu/menu_messages_conversation.xml index c1811cd3c..f1ba3562d 100644 --- a/twidere/src/main/res/menu/menu_messages_conversation.xml +++ b/twidere/src/main/res/menu/menu_messages_conversation.xml @@ -20,10 +20,6 @@ - + @@ -144,6 +145,14 @@ + + + + + + + + diff --git a/twidere/src/main/res/values/dimens.xml b/twidere/src/main/res/values/dimens.xml index b5053f70a..750d5b063 100644 --- a/twidere/src/main/res/values/dimens.xml +++ b/twidere/src/main/res/values/dimens.xml @@ -81,6 +81,7 @@ 26dp 48dp 84dp + 64dp 2dp