Skip to content

Commit 7411754

Browse files
authored
Merge pull request #388 from wordpress-mobile/issue/370-add-toolbar-toggle
Issue/370 add toolbar toggle
2 parents d94be69 + f86c299 commit 7411754

14 files changed

+504
-76
lines changed

aztec/src/main/kotlin/org/wordpress/aztec/toolbar/AztecToolbar.kt

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ import android.view.KeyEvent
99
import android.view.LayoutInflater
1010
import android.view.MenuItem
1111
import android.view.View
12-
import android.widget.FrameLayout
13-
import android.widget.PopupMenu
12+
import android.view.animation.Animation
13+
import android.view.animation.AnimationUtils
14+
import android.widget.*
1415
import android.widget.PopupMenu.OnMenuItemClickListener
15-
import android.widget.Toast
16-
import android.widget.ToggleButton
1716
import org.wordpress.aztec.AztecText
1817
import org.wordpress.aztec.R
1918
import org.wordpress.aztec.TextFormat
@@ -27,18 +26,29 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
2726
private var listMenu: PopupMenu? = null
2827
private var sourceEditor: SourceViewEditText? = null
2928
private var dialogShortcuts: AlertDialog? = null
29+
private var isAdvanced: Boolean = false
30+
private var isExpanded: Boolean = false
3031
private var isMediaModeEnabled: Boolean = false
3132

33+
private lateinit var buttonScroll: HorizontalScrollView
34+
private lateinit var buttonEllipsisCollapse: RippleToggleButton
35+
private lateinit var buttonEllipsisExpand: RippleToggleButton
36+
private lateinit var layoutExpandedTranslateInRight: Animation
37+
private lateinit var layoutExpandedTranslateOutLeft: Animation
38+
private lateinit var ellipsisSpinLeft: Animation
39+
private lateinit var ellipsisSpinRight: Animation
40+
private lateinit var layoutExpanded: LinearLayout
41+
3242
constructor(context: Context) : super(context) {
33-
initView()
43+
initView(null)
3444
}
3545

3646
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
37-
initView()
47+
initView(attrs)
3848
}
3949

4050
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
41-
initView()
51+
initView(attrs)
4252
}
4353

4454
fun setToolbarListener(listener: AztecToolbarClickListener) {
@@ -255,6 +265,8 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
255265
val restoredState = savedState.state
256266
toggleHtmlMode(restoredState.getBoolean("isSourceVisible"))
257267
enableMediaMode(restoredState.getBoolean("isMediaMode"))
268+
isExpanded = restoredState.getBoolean("isExpanded")
269+
setAdvancedState()
258270
}
259271

260272
override fun onSaveInstanceState(): Parcelable {
@@ -263,6 +275,7 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
263275
val bundle = Bundle()
264276
bundle.putBoolean("isSourceVisible", sourceEditor?.visibility == View.VISIBLE)
265277
bundle.putBoolean("isMediaMode", isMediaModeEnabled)
278+
bundle.putBoolean("isExpanded", isExpanded)
266279
savedState.state = bundle
267280
return savedState
268281
}
@@ -283,8 +296,14 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
283296
})
284297
}
285298

286-
private fun initView() {
287-
View.inflate(context, R.layout.aztec_format_bar, this)
299+
private fun initView(attrs: AttributeSet?) {
300+
val styles = context.obtainStyledAttributes(attrs, R.styleable.AztecToolbar, 0, R.style.AztecToolbarStyle)
301+
isAdvanced = styles.getBoolean(R.styleable.AztecToolbar_advanced, false)
302+
styles.recycle()
303+
304+
val layout = if (isAdvanced) R.layout.aztec_format_bar_advanced else R.layout.aztec_format_bar_basic
305+
View.inflate(context, layout, this)
306+
setAdvancedState()
288307

289308
for (toolbarAction in ToolbarAction.values()) {
290309
val button = findViewById(toolbarAction.buttonId)
@@ -314,8 +333,11 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
314333
val actions = ArrayList<ToolbarAction>()
315334

316335
for (action in ToolbarAction.values()) {
317-
val view = findViewById(action.buttonId) as ToggleButton
318-
if (view.isChecked) actions.add(action)
336+
if (action != ToolbarAction.ELLIPSIS_COLLAPSE &&
337+
action != ToolbarAction.ELLIPSIS_EXPAND) {
338+
val view = findViewById(action.buttonId) as ToggleButton
339+
if (view.isChecked) actions.add(action)
340+
}
319341
}
320342

321343
return actions
@@ -375,6 +397,8 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
375397
ToolbarAction.LIST -> listMenu?.show()
376398
ToolbarAction.LINK -> editor!!.showLinkDialog()
377399
ToolbarAction.HTML -> aztecToolbarListener?.onToolbarHtmlModeClicked()
400+
ToolbarAction.ELLIPSIS_COLLAPSE -> animateToolbarCollapse()
401+
ToolbarAction.ELLIPSIS_EXPAND -> animateToolbarExpand()
378402
else -> {
379403
Toast.makeText(context, "Unsupported action", Toast.LENGTH_SHORT).show()
380404
}
@@ -424,6 +448,34 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
424448
return null
425449
}
426450

451+
fun setExpanded(expanded: Boolean) {
452+
isExpanded = expanded
453+
setAdvancedState()
454+
}
455+
456+
private fun animateToolbarCollapse() {
457+
buttonEllipsisCollapse.startAnimation(ellipsisSpinLeft)
458+
isExpanded = false
459+
}
460+
461+
private fun animateToolbarExpand() {
462+
buttonEllipsisExpand.startAnimation(ellipsisSpinRight)
463+
isExpanded = true
464+
}
465+
466+
private fun setAdvancedState() {
467+
if (isAdvanced) {
468+
setButtonViews()
469+
setAnimations()
470+
471+
if (isExpanded) {
472+
showExpandedToolbar()
473+
} else {
474+
showCollapsedToolbar()
475+
}
476+
}
477+
}
478+
427479
private fun selectHeadingMenuItem(textFormats: ArrayList<TextFormat>) {
428480
if (textFormats.size == 0) {
429481
// Select paragraph by default.
@@ -478,6 +530,68 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
478530
}
479531
}
480532

533+
private fun setAnimations() {
534+
layoutExpandedTranslateInRight = AnimationUtils.loadAnimation(context, R.anim.translate_in_right)
535+
536+
layoutExpandedTranslateOutLeft = AnimationUtils.loadAnimation(context, R.anim.translate_out_left)
537+
layoutExpandedTranslateOutLeft.setAnimationListener(
538+
object : Animation.AnimationListener {
539+
override fun onAnimationEnd(animation: Animation) {
540+
layoutExpanded.visibility = View.GONE
541+
}
542+
543+
override fun onAnimationRepeat(animation: Animation) {
544+
}
545+
546+
override fun onAnimationStart(animation: Animation) {
547+
}
548+
}
549+
)
550+
551+
ellipsisSpinLeft = AnimationUtils.loadAnimation(context, R.anim.spin_left_90)
552+
ellipsisSpinLeft.setAnimationListener(
553+
object : Animation.AnimationListener {
554+
override fun onAnimationEnd(animation: Animation) {
555+
buttonEllipsisCollapse.visibility = View.GONE
556+
buttonEllipsisExpand.visibility = View.VISIBLE
557+
}
558+
559+
override fun onAnimationRepeat(animation: Animation) {
560+
}
561+
562+
override fun onAnimationStart(animation: Animation) {
563+
buttonScroll.smoothScrollTo(0, 0)
564+
layoutExpanded.startAnimation(layoutExpandedTranslateOutLeft)
565+
}
566+
}
567+
)
568+
569+
ellipsisSpinRight = AnimationUtils.loadAnimation(context, R.anim.spin_right_90)
570+
ellipsisSpinRight.setAnimationListener(
571+
object : Animation.AnimationListener {
572+
override fun onAnimationEnd(animation: Animation) {
573+
buttonEllipsisCollapse.visibility = View.VISIBLE
574+
buttonEllipsisExpand.visibility = View.GONE
575+
}
576+
577+
override fun onAnimationRepeat(animation: Animation) {
578+
}
579+
580+
override fun onAnimationStart(animation: Animation) {
581+
layoutExpanded.visibility = View.VISIBLE
582+
layoutExpanded.startAnimation(layoutExpandedTranslateInRight)
583+
}
584+
}
585+
)
586+
}
587+
588+
private fun setButtonViews() {
589+
layoutExpanded = findViewById(R.id.format_bar_button_layout_expanded) as LinearLayout
590+
buttonScroll = findViewById(R.id.format_bar_button_scroll) as HorizontalScrollView
591+
buttonEllipsisCollapse = findViewById(R.id.format_bar_button_ellipsis_collapse) as RippleToggleButton
592+
buttonEllipsisExpand = findViewById(R.id.format_bar_button_ellipsis_expand) as RippleToggleButton
593+
}
594+
481595
private fun setHeadingMenu(view: View) {
482596
headingMenu = PopupMenu(context, view)
483597
headingMenu?.setOnMenuItemClickListener(this)
@@ -517,6 +631,18 @@ class AztecToolbar : FrameLayout, OnMenuItemClickListener {
517631
}
518632
}
519633

634+
private fun showCollapsedToolbar() {
635+
layoutExpanded.visibility = View.GONE
636+
buttonEllipsisCollapse.visibility = View.GONE
637+
buttonEllipsisExpand.visibility = View.VISIBLE
638+
}
639+
640+
private fun showExpandedToolbar() {
641+
layoutExpanded.visibility = View.VISIBLE
642+
buttonEllipsisCollapse.visibility = View.VISIBLE
643+
buttonEllipsisExpand.visibility = View.GONE
644+
}
645+
520646
private fun toggleHtmlMode(isHtmlMode: Boolean) {
521647
ToolbarAction.values().forEach { action ->
522648
if (action == ToolbarAction.HTML) {

aztec/src/main/kotlin/org/wordpress/aztec/toolbar/ToolbarAction.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ enum class ToolbarAction constructor(val buttonId: Int, val actionType: ToolbarA
2020
HORIZONTAL_RULE(R.id.format_bar_button_horizontal_rule, ToolbarActionType.LINE_BLOCK, TextFormat.FORMAT_HORIZONTAL_RULE),
2121
MORE(R.id.format_bar_button_more, ToolbarActionType.LINE_BLOCK, TextFormat.FORMAT_MORE),
2222
PAGE(R.id.format_bar_button_page, ToolbarActionType.LINE_BLOCK, TextFormat.FORMAT_PAGE),
23-
HTML(R.id.format_bar_button_html, ToolbarActionType.OTHER, null);
23+
HTML(R.id.format_bar_button_html, ToolbarActionType.OTHER, null),
24+
ELLIPSIS_COLLAPSE(R.id.format_bar_button_ellipsis_collapse, ToolbarActionType.OTHER, null),
25+
ELLIPSIS_EXPAND(R.id.format_bar_button_ellipsis_expand, ToolbarActionType.OTHER, null);
2426

2527
companion object {
2628
fun getToolbarActionForStyle(style: TextFormat): ToolbarAction? {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<overshootInterpolator
4+
xmlns:android="http://schemas.android.com/apk/res/android"
5+
android:tension="3.5" >
6+
</overshootInterpolator>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<set
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:duration="@android:integer/config_shortAnimTime"
4+
android:interpolator="@android:anim/overshoot_interpolator" >
5+
6+
<rotate
7+
android:fromDegrees="0"
8+
android:pivotX="50%"
9+
android:pivotY="50%"
10+
android:toDegrees="-90" >
11+
</rotate>
12+
13+
</set>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<set
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:duration="@android:integer/config_shortAnimTime"
4+
android:interpolator="@android:anim/overshoot_interpolator" >
5+
6+
<rotate
7+
android:fromDegrees="0"
8+
android:pivotX="50%"
9+
android:pivotY="50%"
10+
android:toDegrees="90" >
11+
</rotate>
12+
13+
</set>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<set
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:duration="@android:integer/config_mediumAnimTime"
4+
android:interpolator="@android:anim/accelerate_decelerate_interpolator" >
5+
6+
<translate
7+
android:fromXDelta="-100%"
8+
android:fromYDelta="0%"
9+
android:toXDelta="0%"
10+
android:toYDelta="0%" >
11+
</translate>
12+
13+
</set>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<set
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:duration="@android:integer/config_mediumAnimTime"
4+
android:interpolator="@android:anim/accelerate_decelerate_interpolator" >
5+
6+
<translate
7+
android:fromXDelta="0%"
8+
android:fromYDelta="0%"
9+
android:toXDelta="-100%"
10+
android:toYDelta="0%" >
11+
</translate>
12+
13+
</set>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<vector
4+
xmlns:android="http://schemas.android.com/apk/res/android"
5+
android:height="48dp"
6+
android:width="48dp"
7+
android:viewportHeight="48"
8+
android:viewportWidth="48" >
9+
10+
<!-- @color/grey_darken_20 -->
11+
<path
12+
android:fillColor="#ff4f748e"
13+
android:pathData="M18.5,24c0,1.2-1,2.2-2.2,2.2s-2.2-1-2.2-2.2s1-2.2,2.2-2.2S18.5,22.8,18.5,24z M31.6,21.8c-1.2,0-2.2,1-2.2,2.2 s1,2.2,2.2,2.2c1.2,0,2.2-1,2.2-2.2S32.8,21.8,31.6,21.8z M24,21.8c-1.2,0-2.2,1-2.2,2.2s1,2.2,2.2,2.2c1.2,0,2.2-1,2.2-2.2 S25.2,21.8,24,21.8z" >
14+
</path>
15+
16+
</vector>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<vector
4+
xmlns:android="http://schemas.android.com/apk/res/android"
5+
android:height="48dp"
6+
android:width="48dp"
7+
android:viewportHeight="48"
8+
android:viewportWidth="48" >
9+
10+
<!-- @color/grey_darken_20 -->
11+
<path
12+
android:fillColor="#ff4f748e"
13+
android:pathData="M23.9,29.4c1.2,0,2.2,1,2.2,2.2c0,1.2-1,2.2-2.2,2.2s-2.2-1-2.2-2.2C21.7,30.4,22.7,29.4,23.9,29.4z M21.7,16.3 c0,1.2,1,2.2,2.2,2.2s2.2-1,2.2-2.2c0-1.2-1-2.2-2.2-2.2S21.7,15.1,21.7,16.3z M21.7,23.9c0,1.2,1,2.2,2.2,2.2s2.2-1,2.2-2.2 s-1-2.2-2.2-2.2S21.7,22.7,21.7,23.9z" >
14+
</path>
15+
16+
</vector>

0 commit comments

Comments
 (0)