Allow notes to expand and expand notes edittext. Fixes #1037

This commit is contained in:
Phillip Thelen 2018-08-27 15:54:44 +02:00
parent 81f41f95da
commit 9cf2b1a71b
8 changed files with 201 additions and 65 deletions

View file

@ -20,9 +20,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<ImageButton
android:id="@+id/emoji.toggle.btn0"
android:layout_width="48dp"
@ -33,49 +32,49 @@
android:focusable="true"
android:focusableInTouchMode="true" />
<android.support.design.widget.TextInputLayout
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/TextAppearance.AppCompat">
<net.pherth.android.emoji_library.EmojiEditText
android:id="@+id/task_text_edittext"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:hintTextAppearance="@style/TextAppearance.AppCompat">
<net.pherth.android.emoji_library.EmojiEditText
android:id="@+id/task_text_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="@string/text"
android:textColor="@android:color/black"
android:inputType="textCapSentences" />
</android.support.design.widget.TextInputLayout>
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="@string/text"
android:textColor="@android:color/black"
android:inputType="textCapSentences|textMultiLine"
android:maxLines="3"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageButton
android:id="@+id/emoji.toggle.btn1"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_emoticon_grey600_24dp"
android:background="@drawable/md_transparent"
android:layout_gravity="center_vertical"
android:contentDescription="Toogle Emoji" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/TextAppearance.AppCompat">
<net.pherth.android.emoji_library.EmojiEditText
android:id="@+id/task_notes_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:hint="@string/notes"
android:textColor="@android:color/black"
android:inputType="textCapSentences|textMultiLine" />
</android.support.design.widget.TextInputLayout>
android:layout_gravity="center_horizontal"
android:hint="@string/notes"
android:textColor="@android:color/black"
android:inputType="textCapSentences|textMultiLine" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
<android.support.design.widget.TextInputLayout
@ -145,27 +144,27 @@
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/actions"
android:textAppearance="?android:attr/textAppearanceLarge" />
<CheckBox
android:id="@+id/task_positive_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="11dp"
android:text="@string/positive_habit_form"
android:textAppearance="?android:attr/textAppearanceMedium" />
android:id="@+id/task_positive_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="11dp"
android:text="@string/positive_habit_form"
android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
android:id="@+id/task_negative_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="11dp"
android:text="@string/negative_habit_form"
android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
android:id="@+id/task_negative_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="11dp"
android:text="@string/negative_habit_form"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
@ -403,11 +402,11 @@
android:layout_marginTop="20dp"
android:id="@+id/task_tags_wrapper">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tags"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/tags"
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:layout_width="match_parent"
@ -416,7 +415,7 @@
android:id="@+id/task_tags_checklist">
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout

View file

@ -53,7 +53,7 @@
android:paddingStart="@dimen/task_text_padding"
android:paddingTop="@dimen/task_top_bottom_padding">
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/checkedTextView"
style="@style/Subheader3"
android:textColor="#000"
@ -61,14 +61,22 @@
android:layout_height="wrap_content"
tools:text="Daily Title" />
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/notesTextView"
style="@style/Caption2.Regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
tools:text="Notes" />
<Button
android:id="@+id/expand_notes_button"
android:layout_width="match_parent"
android:layout_height="30dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:text="@string/expand_notes"
android:padding="0dp"
android:textColor="@color/brand_400"/>
<TextView
android:id="@+id/approvalRequiredTextField"
android:layout_width="match_parent"

View file

@ -54,7 +54,7 @@
android:paddingStart="@dimen/task_text_padding"
android:paddingTop="@dimen/task_top_bottom_padding">
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/checkedTextView"
style="@style/Subheader3"
android:textColor="#000"
@ -62,14 +62,23 @@
android:layout_height="wrap_content"
tools:text="Habit Title" />
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/notesTextView"
style="@style/Caption2.Regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
tools:text="Notes"/>
<Button
android:id="@+id/expand_notes_button"
android:layout_width="match_parent"
android:layout_height="30dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:text="@string/expand_notes"
android:padding="0dp"
android:textColor="@color/brand_400"/>
<TextView
android:id="@+id/approvalRequiredTextField"
android:layout_width="match_parent"

View file

@ -33,7 +33,7 @@
android:paddingRight="@dimen/reward_spacing"
android:paddingTop="@dimen/task_top_bottom_padding">
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/checkedTextView"
style="@style/Subheader3"
android:layout_width="match_parent"
@ -41,13 +41,21 @@
android:textColor="#000"
tools:text="Title" />
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/notesTextView"
style="@style/Caption2.Regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Notes"/>
<Button
android:id="@+id/expand_notes_button"
android:layout_width="match_parent"
android:layout_height="30dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:text="@string/expand_notes"
android:padding="0dp"
android:textColor="@color/brand_400"/>
<TextView
android:id="@+id/approvalRequiredTextField"
android:layout_width="match_parent"

View file

@ -53,7 +53,7 @@
android:paddingStart="@dimen/task_text_padding"
android:paddingTop="@dimen/task_top_bottom_padding">
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/checkedTextView"
style="@style/Subheader3"
android:textColor="#000"
@ -61,14 +61,23 @@
android:layout_height="wrap_content"
tools:text="To-Do Title" />
<net.pherth.android.emoji_library.EmojiTextView
<com.habitrpg.android.habitica.ui.views.EllipsisTextView
android:id="@+id/notesTextView"
style="@style/Caption2.Regular"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="3"
android:ellipsize="end"
tools:text="Notes" />
<Button
android:id="@+id/expand_notes_button"
android:layout_width="match_parent"
android:layout_height="30dp"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:text="@string/expand_notes"
android:padding="0dp"
android:textColor="@color/brand_400"/>
<TextView
android:id="@+id/approvalRequiredTextField"
android:layout_width="match_parent"

View file

@ -805,4 +805,6 @@
<string name="daily_tip_9">If you\'re having a tough time, try breaking your tasks down into smaller parts.</string>
<string name="moderator">Moderator</string>
<string name="staff">Staff</string>
<string name="expand_notes">Read More</string>
<string name="collapse_notes">Show Less</string>
</resources>

View file

@ -2,7 +2,9 @@ package com.habitrpg.android.habitica.ui.viewHolders.tasks
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.text.method.LinkMovementMethod
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
@ -15,6 +17,7 @@ import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import com.habitrpg.android.habitica.ui.helpers.bindColor
import com.habitrpg.android.habitica.ui.helpers.bindOptionalView
import com.habitrpg.android.habitica.ui.views.EllipsisTextView
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
@ -27,8 +30,8 @@ abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.Vie
var task: Task? = null
protected var context: Context
private val titleTextView: EmojiTextView by bindView(itemView, R.id.checkedTextView)
private val notesTextView: EmojiTextView by bindView(itemView, R.id.notesTextView)
private val titleTextView: EllipsisTextView by bindView(itemView, R.id.checkedTextView)
private val notesTextView: EllipsisTextView by bindView(itemView, R.id.notesTextView)
internal val rightBorderView: View? by bindOptionalView(itemView, R.id.rightBorderView)
protected val specialTaskTextView: TextView? by bindOptionalView(itemView, R.id.specialTaskText)
private val iconViewChallenge: ImageView? by bindView(itemView, R.id.iconviewChallenge)
@ -36,10 +39,12 @@ abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.Vie
private val iconViewTag: ImageView? by bindView(itemView, R.id.iconviewTag)
private val taskIconWrapper: LinearLayout? by bindView(itemView, R.id.taskIconWrapper)
private val approvalRequiredTextView: TextView? by bindView(itemView, R.id.approvalRequiredTextField)
private val expandNotesButton: Button by bindView(R.id.expand_notes_button)
protected val taskGray: Int by bindColor(itemView.context, R.color.task_gray)
private var openTaskDisabled: Boolean = false
private var taskActionsDisabled: Boolean = false
private var notesExpanded = false
protected open val taskIconWrapperIsVisible: Boolean
get() {
@ -69,16 +74,47 @@ abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.Vie
itemView.isClickable = true
//Re enable when we find a way to only react when a link is tapped.
//notesTextView.setMovementMethod(LinkMovementMethod.getInstance());
//titleTextView.setMovementMethod(LinkMovementMethod.getInstance());
//notesTextView.movementMethod = LinkMovementMethod.getInstance()
//titleTextView.movementMethod = LinkMovementMethod.getInstance()
expandNotesButton.setOnClickListener { expandTask() }
notesTextView.addEllipsesListener(object : EllipsisTextView.EllipsisListener {
override fun ellipsisStateChanged(ellipses: Boolean) {
Single.just(ellipses)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(Consumer{ hasEllipses ->
expandNotesButton.visibility = if (hasEllipses || notesExpanded) View.VISIBLE else View.GONE
}, RxErrorHandler.handleEmptyError())
}
})
context = itemView.context
}
open fun bindHolder(newTask: Task, position: Int) {
private fun expandTask() {
notesExpanded = !notesExpanded
if (notesExpanded) {
notesTextView.maxLines = 100
expandNotesButton.text = context.getString(R.string.collapse_notes)
} else {
notesTextView.maxLines = 3
expandNotesButton.text = context.getString(R.string.expand_notes)
}
}
open fun bindHolder(newTask: Task, position: Int) {
task = newTask
itemView.setBackgroundResource(R.color.white)
if (newTask.notes?.isNotEmpty() == true) {
notesTextView.visibility = View.VISIBLE
//expandNotesButton.visibility = if (notesTextView.hadEllipses() || notesExpanded) View.VISIBLE else View.GONE
} else {
notesTextView.visibility = View.GONE
expandNotesButton.visibility = View.GONE
}
if (canContainMarkdown()) {
if (newTask.parsedText != null) {
titleTextView.text = newTask.parsedText
@ -94,8 +130,8 @@ abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.Vie
newTask.parsedText = parsedText
titleTextView.text = newTask.parsedText
}, RxErrorHandler.handleEmptyError())
newTask.notes.notNull {
Single.just(it)
newTask.notes.notNull {notes ->
Single.just(notes)
.map { MarkdownParser.parseMarkdown(it) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -110,11 +146,6 @@ abstract class BaseTaskViewHolder constructor(itemView: View) : RecyclerView.Vie
titleTextView.text = newTask.text
notesTextView.text = newTask.notes
}
if (newTask.notes?.isNotEmpty() == true) {
notesTextView.visibility = View.VISIBLE
} else {
notesTextView.visibility = View.GONE
}
rightBorderView?.setBackgroundResource(newTask.lightTaskColor)
iconViewReminder?.visibility = if (newTask.reminders?.size ?: 0 > 0) View.VISIBLE else View.GONE

View file

@ -0,0 +1,70 @@
package com.habitrpg.android.habitica.ui.views
/**
* Author: Michael Ritchie, ThanksMister LLC
* Date: 10/16/12
* Web: thanksmister.com
*
* Extension of <code>TextView</code> that adds listener for ellipses changes. This can be used to determine
* if a TextView has an ellipses or not.
*
* Derived from discussion on StackOverflow:
*
* http://stackoverflow.com/questions/4005933/how-do-i-tell-if-my-textview-has-been-ellipsized
*/
import android.content.Context
import android.util.AttributeSet
import net.pherth.android.emoji_library.EmojiTextView
class EllipsisTextView : EmojiTextView {
private val ellipsesListeners = ArrayList<EllipsisListener>()
private var ellipses: Boolean = false
interface EllipsisListener {
fun ellipsisStateChanged(ellipses: Boolean)
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
fun addEllipsesListener(listener: EllipsisListener?) {
if (listener == null) {
throw NullPointerException()
}
ellipsesListeners.add(listener)
}
fun removeEllipsesListener(listener: EllipsisListener) {
ellipsesListeners.remove(listener)
}
fun hadEllipses(): Boolean {
return ellipses
}
override fun layout(l: Int, t: Int, r: Int, b: Int) {
super.layout(l, t, r, b)
ellipses = false
val layout = layout
if (layout != null) {
val lines = layout.lineCount
if (lines > 0) {
if (layout.getEllipsisCount(lines - 1) > 0) {
ellipses = true
}
}
}
for (listener in ellipsesListeners) {
listener.ellipsisStateChanged(ellipses)
}
}
}