reduced status list item child view count

This commit is contained in:
Mariotaku Lee 2017-03-02 20:42:53 +08:00
parent 719794778d
commit 163cc2f88e
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
15 changed files with 234 additions and 225 deletions

View File

@ -76,8 +76,10 @@ install:
before_script: before_script:
# Validate if patches work # Validate if patches work
- patch --dry-run -d twidere < twidere/patches/remove_closed_source_dependencies.patch - patch --dry-run -d twidere < twidere/patches/remove_closed_source_dependencies.patch
# Validate if Google components fetched successfully
- test -f twidere/src/google/AndroidManifest.xml
script: GRADLE_OPTS="-Dkotlin.incremental=false" ./gradlew build --no-daemon --stacktrace script: ./gradlew build --no-daemon --stacktrace
deploy: deploy:
provider: releases provider: releases

View File

@ -20,22 +20,9 @@
package org.mariotaku.twidere.adapter package org.mariotaku.twidere.adapter
import android.content.Context import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.RequestManager import com.bumptech.glide.RequestManager
import com.commonsware.cwac.layouts.AspectLockedFrameLayout
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
import org.mariotaku.twidere.view.MediaPreviewImageView
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
/** /**
@ -47,7 +34,7 @@ class StaggeredGridParcelableStatusesAdapter(
) : ParcelableStatusesAdapter(context, requestManager) { ) : ParcelableStatusesAdapter(context, requestManager) {
override val progressViewIds: IntArray override val progressViewIds: IntArray
get() = intArrayOf(R.id.media_image_progress) get() = intArrayOf(R.id.mediaImageProgress)
override fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder { override fun onCreateStatusViewHolder(parent: ViewGroup): IStatusViewHolder {
val view = inflater.inflate(R.layout.adapter_item_media_status, parent, false) val view = inflater.inflate(R.layout.adapter_item_media_status, parent, false)
@ -57,104 +44,4 @@ class StaggeredGridParcelableStatusesAdapter(
return holder return holder
} }
class MediaStatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : RecyclerView.ViewHolder(itemView), IStatusViewHolder, View.OnClickListener, View.OnLongClickListener {
private val aspectRatioSource = SimpleAspectRatioSource().apply {
setSize(100, 100)
}
private val mediaImageContainer: AspectLockedFrameLayout
private val mediaImageView: MediaPreviewImageView
override val profileImageView: ImageView
private val mediaTextView: TextView
private var listener: IStatusViewHolder.StatusClickListener? = null
init {
mediaImageContainer = itemView.findViewById(R.id.media_image_container) as AspectLockedFrameLayout
mediaImageContainer.setAspectRatioSource(aspectRatioSource)
mediaImageView = itemView.findViewById(R.id.media_image) as MediaPreviewImageView
profileImageView = itemView.findViewById(R.id.media_profile_image) as ImageView
mediaTextView = itemView.findViewById(R.id.media_text) as TextView
}
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean,
displayExtraType: Boolean, displayPinned: Boolean) {
val media = status.media ?: return
if (media.isEmpty()) return
val firstMedia = media[0]
mediaTextView.text = status.text_unescaped
if (firstMedia.width > 0 && firstMedia.height > 0) {
aspectRatioSource.setSize(firstMedia.width, firstMedia.height)
} else {
aspectRatioSource.setSize(100, 100)
}
mediaImageContainer.tag = firstMedia
mediaImageContainer.requestLayout()
mediaImageView.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(firstMedia.type))
val context = itemView.context
adapter.requestManager.loadProfileImage(context, status).into(profileImageView)
// TODO image loaded event and credentials
adapter.requestManager.load(firstMedia.preview_url).into(mediaImageView)
}
override val profileTypeView: ImageView?
get() = null
override fun onClick(v: View) {
when (v.id) {
R.id.itemContent -> {
listener?.onStatusClick(this, layoutPosition)
}
}
}
override fun onLongClick(v: View): Boolean {
return false
}
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey?, id: Long) {
}
override fun setStatusClickListener(listener: IStatusViewHolder.StatusClickListener?) {
this.listener = listener
itemView.findViewById(R.id.itemContent).setOnClickListener(this)
}
override fun setTextSize(textSize: Float) {
}
override fun playLikeAnimation(listener: LikeAnimationDrawable.OnLikedListener) {
}
fun setOnClickListeners() {
setStatusClickListener(adapter.statusClickListener)
}
fun setupViewOptions() {
setTextSize(adapter.textSize)
}
private class SimpleAspectRatioSource : AspectLockedFrameLayout.AspectRatioSource {
private var width: Int = 0
private var height: Int = 0
override fun getWidth(): Int {
return width
}
override fun getHeight(): Int {
return height
}
fun setSize(width: Int, height: Int) {
this.width = width
this.height = height
}
}
}
} }

View File

@ -27,6 +27,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
import jp.wasabeef.glide.transformations.CropCircleTransformation import jp.wasabeef.glide.transformations.CropCircleTransformation
import org.mariotaku.twidere.R import org.mariotaku.twidere.R
import org.mariotaku.twidere.annotation.ImageShapeStyle import org.mariotaku.twidere.annotation.ImageShapeStyle
import org.mariotaku.twidere.extension.model.getBestProfileBanner
import org.mariotaku.twidere.extension.model.user import org.mariotaku.twidere.extension.model.user
import org.mariotaku.twidere.model.* import org.mariotaku.twidere.model.*
import org.mariotaku.twidere.util.Utils import org.mariotaku.twidere.util.Utils
@ -100,6 +101,10 @@ fun RequestManager.loadOriginalProfileImage(context: Context, user: ParcelableUs
return configureLoadProfileImage(context, shapeStyle) { load(original) } return configureLoadProfileImage(context, shapeStyle) { load(original) }
} }
fun RequestManager.loadProfileBanner(context: Context, user: ParcelableUser, width: Int): DrawableTypeRequest<String?> {
return load(user.getBestProfileBanner(width))
}
internal inline fun <T> configureLoadProfileImage(context: Context, shapeStyle: Int, internal inline fun <T> configureLoadProfileImage(context: Context, shapeStyle: Int,
create: () -> DrawableTypeRequest<T>): DrawableRequestBuilder<T> { create: () -> DrawableTypeRequest<T>): DrawableRequestBuilder<T> {
val builder = create() val builder = create()

View File

@ -31,6 +31,7 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.OnScrollListener import android.support.v7.widget.RecyclerView.OnScrollListener
import android.view.* import android.view.*
import com.bumptech.glide.Glide
import com.squareup.otto.Subscribe import com.squareup.otto.Subscribe
import edu.tsinghua.hotmobi.HotMobiLogger import edu.tsinghua.hotmobi.HotMobiLogger
import edu.tsinghua.hotmobi.model.MediaEvent import edu.tsinghua.hotmobi.model.MediaEvent
@ -101,7 +102,7 @@ abstract class AbsActivitiesFragment protected constructor() :
registerForContextMenu(recyclerView) registerForContextMenu(recyclerView)
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter,
this) this)
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, true) pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, true, Glide.with(this))
val loaderArgs = Bundle(arguments) val loaderArgs = Bundle(arguments)
loaderArgs.putBoolean(EXTRA_FROM_USER, true) loaderArgs.putBoolean(EXTRA_FROM_USER, true)

View File

@ -32,6 +32,7 @@ import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.OnScrollListener import android.support.v7.widget.RecyclerView.OnScrollListener
import android.view.* import android.view.*
import com.bumptech.glide.Glide
import com.squareup.otto.Subscribe import com.squareup.otto.Subscribe
import edu.tsinghua.hotmobi.HotMobiLogger import edu.tsinghua.hotmobi.HotMobiLogger
import edu.tsinghua.hotmobi.model.MediaEvent import edu.tsinghua.hotmobi.model.MediaEvent
@ -128,7 +129,7 @@ abstract class AbsStatusesFragment : AbsContentListRecyclerViewFragment<Parcelab
adapter.statusClickListener = this adapter.statusClickListener = this
registerForContextMenu(recyclerView) registerForContextMenu(recyclerView)
navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, this) navigationHelper = RecyclerViewNavigationHelper(recyclerView, layoutManager, adapter, this)
pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, true) pauseOnScrollListener = PauseRecyclerViewOnScrollListener(false, true, Glide.with(this))
if (shouldInitLoader) { if (shouldInitLoader) {
initLoaderIfNeeded() initLoaderIfNeeded()

View File

@ -71,6 +71,7 @@ import org.mariotaku.twidere.annotation.Referral
import org.mariotaku.twidere.constant.KeyboardShortcutConstants.* import org.mariotaku.twidere.constant.KeyboardShortcutConstants.*
import org.mariotaku.twidere.constant.extraFeaturesNoticeVersionKey import org.mariotaku.twidere.constant.extraFeaturesNoticeVersionKey
import org.mariotaku.twidere.constant.profileImageStyleKey import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.loadProfileBanner
import org.mariotaku.twidere.extension.loadProfileImage import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.extension.model.setActivated import org.mariotaku.twidere.extension.model.setActivated
import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo import org.mariotaku.twidere.fragment.AccountsDashboardFragment.AccountsInfo
@ -80,10 +81,8 @@ import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.SupportTabSpec import org.mariotaku.twidere.model.SupportTabSpec
import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.AccountUtils import org.mariotaku.twidere.model.util.AccountUtils
import org.mariotaku.twidere.model.util.ParcelableUserUtils
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
import org.mariotaku.twidere.util.* import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.InternalTwitterContentUtils.getBestBannerUrl
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback
import org.mariotaku.twidere.view.ShapedImageView import org.mariotaku.twidere.view.ShapedImageView
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -502,8 +501,8 @@ class AccountsDashboardFragment : BaseFragment(), LoaderCallbacks<AccountsInfo>,
val defWidth = res.displayMetrics.widthPixels val defWidth = res.displayMetrics.widthPixels
val width = if (bannerWidth > 0) bannerWidth else defWidth val width = if (bannerWidth > 0) bannerWidth else defWidth
val bannerView = accountProfileBanner.nextView as ImageView val bannerView = accountProfileBanner.nextView as ImageView
val url = getBestBannerUrl(ParcelableUserUtils.getProfileBannerUrl(account.user), width)
Glide.with(this).load(url).into(bannerView) Glide.with(this).loadProfileBanner(context, account.user, width).into(bannerView)
} }
private fun displayCurrentAccount(profileImageSnapshot: Drawable?) { private fun displayCurrentAccount(profileImageSnapshot: Drawable?) {

View File

@ -105,7 +105,7 @@ import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.constant.profileImageStyleKey import org.mariotaku.twidere.constant.profileImageStyleKey
import org.mariotaku.twidere.extension.applyTheme import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.extension.loadOriginalProfileImage import org.mariotaku.twidere.extension.loadOriginalProfileImage
import org.mariotaku.twidere.extension.loadProfileImage import org.mariotaku.twidere.extension.loadProfileBanner
import org.mariotaku.twidere.extension.model.applyTo import org.mariotaku.twidere.extension.model.applyTo
import org.mariotaku.twidere.fragment.AbsStatusesFragment.StatusesFragmentDelegate import org.mariotaku.twidere.fragment.AbsStatusesFragment.StatusesFragmentDelegate
import org.mariotaku.twidere.fragment.UserTimelineFragment.UserTimelineFragmentDelegate import org.mariotaku.twidere.fragment.UserTimelineFragment.UserTimelineFragmentDelegate
@ -521,9 +521,8 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
} }
val defWidth = resources.displayMetrics.widthPixels val defWidth = resources.displayMetrics.widthPixels
val width = if (bannerWidth > 0) bannerWidth else defWidth val width = if (bannerWidth > 0) bannerWidth else defWidth
val bannerUrl = getBestBannerUrl(ParcelableUserUtils.getProfileBannerUrl(user), width)
val requestManager = Glide.with(this) val requestManager = Glide.with(this)
requestManager.load(bannerUrl).into(profileBanner) requestManager.loadProfileBanner(context, user, width).into(profileBanner)
requestManager.loadOriginalProfileImage(context, user, profileImage.style).into(profileImage) requestManager.loadOriginalProfileImage(context, user, profileImage.style).into(profileImage)
val relationship = relationship val relationship = relationship
if (relationship == null) { if (relationship == null) {

View File

@ -50,8 +50,8 @@ import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.* import org.mariotaku.twidere.TwidereConstants.*
import org.mariotaku.twidere.activity.ColorPickerDialogActivity import org.mariotaku.twidere.activity.ColorPickerDialogActivity
import org.mariotaku.twidere.activity.ThemedMediaPickerActivity import org.mariotaku.twidere.activity.ThemedMediaPickerActivity
import org.mariotaku.twidere.extension.loadProfileBanner
import org.mariotaku.twidere.extension.loadProfileImage import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.extension.model.getBestProfileBanner
import org.mariotaku.twidere.extension.model.newMicroBlogInstance import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.loader.ParcelableUserLoader import org.mariotaku.twidere.loader.ParcelableUserLoader
import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.AccountDetails
@ -290,7 +290,7 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
editUrl.setText(if (isEmpty(user.url_expanded)) user.url else user.url_expanded) editUrl.setText(if (isEmpty(user.url_expanded)) user.url else user.url_expanded)
Glide.with(this).loadProfileImage(context, user).into(profileImage) Glide.with(this).loadProfileImage(context, user).into(profileImage)
Glide.with(this).load(user.getBestProfileBanner(resources.displayMetrics.widthPixels)).into(profileBanner) Glide.with(this).loadProfileBanner(context, user, resources.displayMetrics.widthPixels).into(profileBanner)
Glide.with(this).load(user.profile_background_url).into(profileBackground) Glide.with(this).load(user.profile_background_url).into(profileBackground)
linkColor.color = user.link_color linkColor.color = user.link_color

View File

@ -20,22 +20,27 @@
package org.mariotaku.twidere.util.imageloader package org.mariotaku.twidere.util.imageloader
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import com.bumptech.glide.RequestManager
class PauseRecyclerViewOnScrollListener( class PauseRecyclerViewOnScrollListener(
private val pauseOnScroll: Boolean, private val pauseOnScroll: Boolean,
private val pauseOnFling: Boolean private val pauseOnFling: Boolean,
private val requestManager: RequestManager
) : RecyclerView.OnScrollListener() { ) : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
when (newState) { when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> { RecyclerView.SCROLL_STATE_IDLE -> {
// TODO resume media load if (!requestManager.isPaused) return
requestManager.resumeRequests()
} }
RecyclerView.SCROLL_STATE_DRAGGING -> if (this.pauseOnScroll) { RecyclerView.SCROLL_STATE_DRAGGING -> if (this.pauseOnScroll) {
// TODO pause media load if (requestManager.isPaused) return
requestManager.pauseRequests()
} }
RecyclerView.SCROLL_STATE_SETTLING -> if (this.pauseOnFling) { RecyclerView.SCROLL_STATE_SETTLING -> if (this.pauseOnFling) {
// TODO pause media load if (requestManager.isPaused) return
requestManager.pauseRequests()
} }
} }
} }

View File

@ -58,15 +58,12 @@ class CardMediaContainer(context: Context, attrs: AttributeSet? = null) : ViewGr
fun displayMedia(vararg imageRes: Int) { fun displayMedia(vararg imageRes: Int) {
val k = imageRes.size val k = imageRes.size
for (i in 0 until childCount) { for (i in 0 until childCount) {
val child = getChildAt(i) val child = getChildAt(i) as ImageView
val imageView = child.findViewById(R.id.mediaPreview) as ImageView
val progress = child.findViewById(R.id.media_preview_progress)
progress.visibility = View.GONE
if (i < k) { if (i < k) {
imageView.setImageResource(imageRes[i]) child.setImageResource(imageRes[i])
child.visibility = View.VISIBLE child.visibility = View.VISIBLE
} else { } else {
imageView.setImageDrawable(null) child.setImageDrawable(null)
child.visibility = View.GONE child.visibility = View.GONE
} }
} }
@ -85,17 +82,16 @@ class CardMediaContainer(context: Context, attrs: AttributeSet? = null) : ViewGr
val clickListener = ImageGridClickListener(mediaClickListener, accountId, extraId) val clickListener = ImageGridClickListener(mediaClickListener, accountId, extraId)
val mediaSize = media.size val mediaSize = media.size
for (i in 0 until childCount) { for (i in 0 until childCount) {
val child = getChildAt(i) val child = getChildAt(i) as ImageView
if (mediaClickListener != null) { if (mediaClickListener != null) {
child.setOnClickListener(clickListener) child.setOnClickListener(clickListener)
} }
val imageView = child.findViewById(R.id.mediaPreview) as ImageView
when (style) { when (style) {
PreviewStyle.REAL_SIZE, PreviewStyle.CROP -> { PreviewStyle.REAL_SIZE, PreviewStyle.CROP -> {
imageView.scaleType = ScaleType.CENTER_CROP child.scaleType = ScaleType.CENTER_CROP
} }
PreviewStyle.SCALE -> { PreviewStyle.SCALE -> {
imageView.scaleType = ScaleType.FIT_CENTER child.scaleType = ScaleType.FIT_CENTER
} }
} }
if (i < mediaSize) { if (i < mediaSize) {
@ -106,16 +102,16 @@ class CardMediaContainer(context: Context, attrs: AttributeSet? = null) : ViewGr
item.media_url item.media_url
} }
if (withCredentials) { if (withCredentials) {
requestManager.load(url).into(imageView) requestManager.load(url).into(child)
// TODO handle load progress w/ authentication // TODO handle load progress w/ authentication
// loader.displayPreviewImageWithCredentials(imageView, url, accountId, loadingHandler, video) // loader.displayPreviewImageWithCredentials(imageView, url, accountId, loadingHandler, video)
} else { } else {
requestManager.load(url).into(imageView) requestManager.load(url).into(child)
// TODO handle load progress // TODO handle load progress
// loader.displayPreviewImage(imageView, url, loadingHandler, video) // loader.displayPreviewImage(imageView, url, loadingHandler, video)
} }
if (imageView is MediaPreviewImageView) { if (child is MediaPreviewImageView) {
imageView.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(item.type)) child.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(item.type))
} }
if (item.alt_text.isNullOrEmpty()) { if (item.alt_text.isNullOrEmpty()) {
child.contentDescription = context.getString(R.string.media) child.contentDescription = context.getString(R.string.media)

View File

@ -0,0 +1,143 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.adapter
import android.support.v7.widget.RecyclerView
import android.view.View
import android.widget.ImageView
import com.commonsware.cwac.layouts.AspectLockedFrameLayout
import kotlinx.android.synthetic.main.adapter_item_media_status.view.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
import org.mariotaku.twidere.model.ParcelableMedia
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
class MediaStatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : RecyclerView.ViewHolder(itemView), IStatusViewHolder, View.OnClickListener, View.OnLongClickListener {
private val aspectRatioSource = SimpleAspectRatioSource().apply {
setSize(100, 100)
}
private val mediaImageContainer = itemView.mediaImageContainer
private val mediaImageView = itemView.mediaImage
override val profileImageView: ImageView = itemView.mediaProfileImage
private val mediaTextView = itemView.mediaText
private var listener: IStatusViewHolder.StatusClickListener? = null
override val profileTypeView: ImageView?
get() = null
init {
mediaImageContainer.setAspectRatioSource(aspectRatioSource)
}
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean,
displayExtraType: Boolean, displayPinned: Boolean) {
val media = status.media ?: return
if (media.isEmpty()) return
val firstMedia = media[0]
var displayEnd = -1
if (status.extras.display_text_range != null) {
displayEnd = status.extras.display_text_range!![1]
}
if (displayEnd >= 0) {
mediaTextView.text = status.text_unescaped.subSequence(0, displayEnd)
} else {
mediaTextView.text = status.text_unescaped
}
if (firstMedia.width > 0 && firstMedia.height > 0) {
aspectRatioSource.setSize(firstMedia.width, firstMedia.height)
} else {
aspectRatioSource.setSize(100, 100)
}
mediaImageContainer.tag = firstMedia
mediaImageContainer.requestLayout()
mediaImageView.setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(firstMedia.type))
val context = itemView.context
adapter.requestManager.loadProfileImage(context, status).into(profileImageView)
// TODO image loaded event and credentials
adapter.requestManager.load(firstMedia.preview_url).into(mediaImageView)
}
override fun onClick(v: View) {
when (v.id) {
R.id.itemContent -> {
listener?.onStatusClick(this, layoutPosition)
}
}
}
override fun onLongClick(v: View): Boolean {
return false
}
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey?, id: Long) {
}
override fun setStatusClickListener(listener: IStatusViewHolder.StatusClickListener?) {
this.listener = listener
itemView.findViewById(R.id.itemContent).setOnClickListener(this)
}
override fun setTextSize(textSize: Float) {
}
override fun playLikeAnimation(listener: LikeAnimationDrawable.OnLikedListener) {
}
fun setOnClickListeners() {
setStatusClickListener(adapter.statusClickListener)
}
fun setupViewOptions() {
setTextSize(adapter.textSize)
}
private class SimpleAspectRatioSource : AspectLockedFrameLayout.AspectRatioSource {
private var width: Int = 0
private var height: Int = 0
override fun getWidth(): Int {
return width
}
override fun getHeight(): Int {
return height
}
fun setSize(width: Int, height: Int) {
this.width = width
this.height = height
}
}
}

View File

@ -344,7 +344,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
mediaPreview.visibility = View.GONE mediaPreview.visibility = View.GONE
} }
var displayEnd = -1 var displayEnd = -1
if (status.extras.display_text_range != null) { if (status.extras.display_text_range != null) {
displayEnd = status.extras.display_text_range!![1] displayEnd = status.extras.display_text_range!![1]

View File

@ -21,6 +21,7 @@
android:id="@+id/itemContent" android:id="@+id/itemContent"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/element_spacing_small" android:layout_margin="@dimen/element_spacing_small"
@ -36,20 +37,21 @@
android:orientation="vertical"> android:orientation="vertical">
<com.commonsware.cwac.layouts.AspectLockedFrameLayout <com.commonsware.cwac.layouts.AspectLockedFrameLayout
android:id="@+id/media_image_container" android:id="@+id/mediaImageContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<org.mariotaku.twidere.view.MediaPreviewImageView <org.mariotaku.twidere.view.MediaPreviewImageView
android:id="@+id/media_image" android:id="@+id/mediaImage"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:contentDescription="@string/media" android:contentDescription="@string/media"
android:foregroundGravity="center" android:foregroundGravity="center"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"
tools:src="@drawable/featured_graphics"/>
<ProgressBar <ProgressBar
android:id="@+id/media_image_progress" android:id="@+id/mediaImageProgress"
style="?android:progressBarStyleHorizontal" style="?android:progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -58,27 +60,33 @@
</com.commonsware.cwac.layouts.AspectLockedFrameLayout> </com.commonsware.cwac.layouts.AspectLockedFrameLayout>
<org.mariotaku.twidere.view.ColorLabelRelativeLayout <org.mariotaku.twidere.view.ColorLabelRelativeLayout
android:id="@+id/media_info_container" android:id="@+id/mediaInfoContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/element_spacing_small"> android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.ProfileImageView <org.mariotaku.twidere.view.ProfileImageView
android:id="@+id/media_profile_image" android:id="@+id/mediaProfileImage"
style="?profileImageStyle" style="?profileImageStyle"
android:layout_width="@dimen/element_size_small" android:layout_width="@dimen/element_size_small"
android:layout_height="@dimen/element_size_small"/> android:layout_height="@dimen/element_size_small"
tools:src="@drawable/ic_profile_image_twidere"/>
<org.mariotaku.twidere.view.FixedTextView <org.mariotaku.twidere.view.FixedTextView
android:id="@+id/media_text" android:id="@+id/mediaText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignTop="@+id/media_profile_image" android:layout_alignTop="@+id/mediaProfileImage"
android:layout_marginLeft="@dimen/element_spacing_small" android:layout_marginLeft="@dimen/element_spacing_small"
android:layout_marginStart="@dimen/element_spacing_small" android:layout_marginStart="@dimen/element_spacing_small"
android:layout_toEndOf="@+id/media_profile_image" android:layout_toEndOf="@+id/mediaProfileImage"
android:layout_toRightOf="@+id/media_profile_image" android:layout_toRightOf="@+id/mediaProfileImage"
android:ellipsize="end"/> android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="2"
android:minHeight="@dimen/element_size_small"
android:textColor="?android:textColorPrimary"
tools:text="@string/sample_status_text"/>
</org.mariotaku.twidere.view.ColorLabelRelativeLayout> </org.mariotaku.twidere.view.ColorLabelRelativeLayout>
</LinearLayout> </LinearLayout>

View File

@ -23,40 +23,48 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
tools:showIn="@layout/list_item_status"> tools:showIn="@layout/list_item_status">
<com.commonsware.cwac.layouts.AspectLockedFrameLayout <org.mariotaku.twidere.view.MediaPreviewImageView
android:id="@+id/media_preview_item_0" android:id="@+id/mediaPreviewItem0"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:foreground="?selectableItemBackground"> android:contentDescription="@string/media"
android:foreground="?selectableItemBackground"
android:foregroundGravity="center"
android:scaleType="centerCrop"
tools:ignore="DuplicateIncludedIds"
tools:src="@drawable/featured_graphics"/>
<include layout="@layout/layout_card_media_preview_item"/> <org.mariotaku.twidere.view.MediaPreviewImageView
</com.commonsware.cwac.layouts.AspectLockedFrameLayout> android:id="@+id/mediaPreviewItem1"
<com.commonsware.cwac.layouts.AspectLockedFrameLayout
android:id="@+id/media_preview_item_1"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:foreground="?selectableItemBackground"> android:contentDescription="@string/media"
android:foreground="?selectableItemBackground"
android:foregroundGravity="center"
android:scaleType="centerCrop"
tools:ignore="DuplicateIncludedIds"
tools:src="@drawable/featured_graphics"/>
<include layout="@layout/layout_card_media_preview_item"/> <org.mariotaku.twidere.view.MediaPreviewImageView
</com.commonsware.cwac.layouts.AspectLockedFrameLayout> android:id="@+id/mediaPreviewItem2"
<com.commonsware.cwac.layouts.AspectLockedFrameLayout
android:id="@+id/media_preview_item_2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:foreground="?selectableItemBackground"> android:contentDescription="@string/media"
android:foreground="?selectableItemBackground"
android:foregroundGravity="center"
android:scaleType="centerCrop"
tools:ignore="DuplicateIncludedIds"
tools:src="@drawable/featured_graphics"/>
<include layout="@layout/layout_card_media_preview_item"/> <org.mariotaku.twidere.view.MediaPreviewImageView
</com.commonsware.cwac.layouts.AspectLockedFrameLayout> android:id="@+id/mediaPreviewItem3"
<com.commonsware.cwac.layouts.AspectLockedFrameLayout
android:id="@+id/media_preview_item_3"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:foreground="?selectableItemBackground"> android:contentDescription="@string/media"
android:foreground="?selectableItemBackground"
android:foregroundGravity="center"
android:scaleType="centerCrop"
tools:ignore="DuplicateIncludedIds"
tools:src="@drawable/featured_graphics"/>
<include layout="@layout/layout_card_media_preview_item"/>
</com.commonsware.cwac.layouts.AspectLockedFrameLayout>
</merge> </merge>

View File

@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.mariotaku.twidere.view.MediaPreviewImageView
android:id="@+id/mediaPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/media"
android:foregroundGravity="center"
android:scaleType="centerCrop"
tools:ignore="DuplicateIncludedIds"
tools:src="@drawable/featured_graphics"/>
<ProgressBar
android:id="@+id/media_preview_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/element_spacing_large"
android:visibility="gone"/>
</merge>