Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #138: Topic train fragment Low-fi UI (Part 3) #203

Merged
merged 19 commits into from
Oct 8, 2019
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ dependencies {
'androidx.constraintlayout:constraintlayout:1.1.3',
'androidx.core:core-ktx:1.0.2',
'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha03',
'androidx.recyclerview:recyclerview:1.0.0',
'com.google.dagger:dagger:2.24',
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1",
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/org/oppia/app/topic/train/SkillInterface.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.oppia.app.topic.train

/** Interface to update the selectedSkillList in [TopicTrainFragmentPresenter]. */
interface SkillInterface {
/** This skill will get added to selectedSkillList in [TopicTrainFragmentPresenter] */
fun skillSelected(skill: String)
/** This skill will get removed from selectedSkillList in [TopicTrainFragmentPresenter] */
fun skillUnselected(skill: String)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.oppia.app.topic.train;

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.databinding.library.baseAdapters.BR
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.topic_train_skill_view.view.*
import org.oppia.app.R
import org.oppia.app.databinding.TopicTrainSkillViewBinding

/** Adapter to bind skills to [RecyclerView] inside [TopicTrainFragment]. **/
class SkillSelectionAdapter(
private val skillList: List<String>,
private val skillInterface: SkillInterface
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding =
DataBindingUtil.inflate<TopicTrainSkillViewBinding>(
inflater,
R.layout.topic_train_skill_view,
parent,
false
)
return SkillViewHolder(binding)
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as SkillViewHolder).bind(skillList[position], position)
}

override fun getItemCount(): Int {
return skillList.size
}

private inner class SkillViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root) {
internal fun bind(rawString: String?, position: Int) {
binding.setVariable(BR.skill, rawString)
binding.root.skill_check_box.setOnCheckedChangeListener { buttonView, isChecked ->
val skill = skillList[position]
if (isChecked) {
skillInterface.skillSelected(skill)
} else {
skillInterface.skillUnselected(skill)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ class TopicTrainFragment : InjectableFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return topicTrainFragmentPresenter.handleCreateView(inflater, container)
}

fun submitButtonClicked(){
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
// List of selected skills when submit button is clicked.
val skillList = topicTrainFragmentPresenter.getSelectedSkillList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,61 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import org.oppia.app.databinding.TopicTrainFragmentBinding
import org.oppia.app.fragment.FragmentScope
import org.oppia.app.viewmodel.ViewModelProvider
import javax.inject.Inject

/** The presenter for [TopicTrainFragment]. */
@FragmentScope
class TopicTrainFragmentPresenter @Inject constructor(
private val fragment: Fragment
) {
private val fragment: Fragment,
private val viewModelProvider: ViewModelProvider<TopicTrainViewModel>
) : SkillInterface {
private val selectedSkillList = ArrayList<String>()

fun handleCreateView(inflater: LayoutInflater, container: ViewGroup?): View? {
val skillAdapter = SkillSelectionAdapter(dummySkillList(), this)

val binding = TopicTrainFragmentBinding.inflate(inflater, container, /* attachToRoot= */ false)
binding.skillRecyclerView.apply {
adapter = skillAdapter
layoutManager = LinearLayoutManager(context)
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
}
binding.let {
it.viewModel = getTopicTrainViewModel()
it.lifecycleOwner = fragment
}
return binding.root
}

private fun getTopicTrainViewModel(): TopicTrainViewModel {
return viewModelProvider.getForFragment(fragment, TopicTrainViewModel::class.java)
}

override fun skillSelected(skill: String) {
selectedSkillList.add(skill)
getTopicTrainViewModel().selectedSkillList(selectedSkillList)
}

override fun skillUnselected(skill: String) {
selectedSkillList.remove(skill)
getTopicTrainViewModel().selectedSkillList(selectedSkillList)
}

private fun dummySkillList(): List<String> {
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
val skillList = ArrayList<String>()
skillList.add("Identify the Parts of a Fraction")
skillList.add("Writing Fractions")
skillList.add("Equivalent Fractions")
skillList.add("Mixed Numbers and Improper Fractions")
skillList.add("Comparing Fractions")
skillList.add("Adding and Subtracting Fractions")
skillList.add("Multiplying Fractions")
skillList.add("Dividing Fractions")
return skillList
}

fun getSelectedSkillList() = selectedSkillList
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.oppia.app.topic.train

import androidx.databinding.ObservableField
import androidx.lifecycle.ViewModel
import org.oppia.app.fragment.FragmentScope
import javax.inject.Inject

/** [ViewModel] for showing skills in train fragment. */
@FragmentScope
class TopicTrainViewModel @Inject constructor() : ViewModel() {
var isSubmitButtonActive = ObservableField<Boolean>(false)

fun selectedSkillList(selectedSkillList: ArrayList<String>) {
rt4914 marked this conversation as resolved.
Show resolved Hide resolved
isSubmitButtonActive.set(selectedSkillList.isNotEmpty())
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/state_button_primary_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="@dimen/state_previous_next_button_radius"/>
<solid
android:color="@color/colorPrimary"/>
</shape>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="@android:color/transparent"/>
</shape>
59 changes: 53 additions & 6 deletions app/src/main/res/layout/topic_train_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,64 @@
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View"/>
<variable
name="topicTrainFragment"
type="org.oppia.app.topic.train.TopicTrainFragment"/>
<variable
name="viewModel"
type="org.oppia.app.topic.train.TopicTrainViewModel"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/dummy_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is dummy TextView for testing"
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="32dp">
<TextView
android:id="@+id/master_skills_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/topic_train_master_these_skills"
android:textColor="@color/oppiaPrimaryText"
android:textSize="20sp"/>
<TextView
android:id="@+id/skills_description_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/topic_train_skills_description"
android:textColor="@color/oppiaSecondaryText"
android:textSize="16sp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/skill_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
<Button
android:id="@+id/topic_train_start_button"
style="@style/StateButtonInactive"
android:layout_gravity="center_horizontal"
android:layout_marginTop="24dp"
android:background="@{viewModel.isSubmitButtonActive() ? @drawable/state_button_primary_background :@drawable/state_button_transparent_background}"
android:clickable="@{viewModel.isSubmitButtonActive()}"
android:onClick="@{(v) -> topicTrainFragment.submitButtonClicked()}"
android:text="@string/topic_train_start"
android:textColor="@{viewModel.isSubmitButtonActive()? @color/white : @color/submitButtonInactive}"/>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
28 changes: 28 additions & 0 deletions app/src/main/res/layout/topic_train_skill_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="skill"
type="java.lang.String"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/skill_check_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
android:drawablePadding="4dp"
android:gravity="center_vertical"
android:text="@{skill}"
android:textColor="@color/oppiaPrimaryText"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
4 changes: 4 additions & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
<color name="ic_launcher_background">#26A69A</color>
<!-- OPPIA COLORS -->
<color name="oppiaDarkBlue">#2D4A9D</color>
<color name="oppiaPrimaryText">#333333</color>
<color name="oppiaSecondaryText">#666666</color>
<!-- BASIC COLORS -->
<color name="white">#FFFFFF</color>
<!-- AUDIO COMPONENT -->
<color name="audioComponentBackground">@color/oppiaDarkBlue</color>
<!-- SUBMIT BUTTON INACTIVE -->
<color name="submitButtonInactive">#56000000</color>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
<dimen name="audio_fragment_corner_radius">8dp</dimen>
<dimen name="audio_fragment_margin">32dp</dimen>
<dimen name="cellular_data_dialog_padding">24dp</dimen>
<dimen name="state_previous_next_button_radius">4dp</dimen>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@
<string name="cellular_data_alert_dialog_title">Currently on Cellular Data</string>
<string name="cellular_data_alert_dialog_description">Streaming audio may use a lot of cellular data.</string>
<string name="cellular_data_alert_dialog_checkbox">Don\'t show this message again</string>
<string name="topic_train_master_these_skills">Master These Skills</string>
<string name="topic_train_skills_description">Select or unselect skills that you want to practice</string>
<string name="topic_train_start">Start</string>
</resources>
27 changes: 27 additions & 0 deletions app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,31 @@
<item name="android:windowEnterAnimation">@anim/slide_up</item>
<item name="android:windowExitAnimation">@anim/slide_down</item>
</style>

<!-- STATE BUTTON ACTIVE STYLE -->
<style name="StateButtonActive" parent="TextAppearance.AppCompat.Widget.Button">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/state_button_primary_background</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:paddingStart">16dp</item>
<item name="android:paddingEnd">16dp</item>
<item name="android:textAllCaps">true</item>
<item name="android:textColor">@color/white</item>
<item name="android:textSize">14sp</item>
<item name="android:clickable">true</item>
</style>

<!-- STATE BUTTON INACTIVE STYLE -->
<style name="StateButtonInactive" parent="TextAppearance.AppCompat.Widget.Button">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">8dp</item>
<item name="android:textAllCaps">true</item>
<item name="android:background">@android:color/transparent</item>
<item name="android:textColor">#56000000</item>
<item name="android:textSize">14sp</item>
<item name="android:clickable">false</item>
</style>
</resources>