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 #2116: revert "#4874 Move PromotedStoryListAdapter to BindableAdapter" #4951

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ VIEW_MODELS_WITH_RESOURCE_IMPORTS = [
"src/main/java/org/oppia/android/app/home/promotedlist/PromotedStoryListViewModel.kt",
"src/main/java/org/oppia/android/app/home/promotedlist/PromotedStoryViewModel.kt",
"src/main/java/org/oppia/android/app/home/recentlyplayed/PromotedStoryViewModel.kt",
"src/main/java/org/oppia/android/app/home/recentlyplayed/RecentlyPlayedViewModel.kt",
"src/main/java/org/oppia/android/app/home/topiclist/TopicSummaryViewModel.kt",
"src/main/java/org/oppia/android/app/onboarding/OnboadingSlideViewModel.kt",
"src/main/java/org/oppia/android/app/onboarding/OnboardingViewModel.kt",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import androidx.annotation.NonNull;
import androidx.core.view.MarginLayoutParamsCompat;
import androidx.core.view.ViewCompat;
import androidx.databinding.BindingAdapter;

/** Holds all custom binding adapters that set margin values. */
Expand All @@ -14,7 +14,12 @@ public final class MarginBindingAdapters {
public static void setLayoutMarginStart(@NonNull View view, float marginStart) {
if (view.getLayoutParams() instanceof MarginLayoutParams) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
MarginLayoutParamsCompat.setMarginStart(params, (int) marginStart);
float marginEnd = params.getMarginEnd();
if (isRtlLayout(view)) {
setLayoutDirectionalMargins(view, (int) marginEnd, (int) marginStart);
} else {
setLayoutDirectionalMargins(view, (int) marginStart, (int) marginEnd);
}
view.requestLayout();
}
}
Expand All @@ -24,17 +29,36 @@ public static void setLayoutMarginStart(@NonNull View view, float marginStart) {
public static void setLayoutMarginEnd(@NonNull View view, float marginEnd) {
if (view.getLayoutParams() instanceof MarginLayoutParams) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
MarginLayoutParamsCompat.setMarginEnd(params, (int) marginEnd);
float marginStart = params.getMarginStart();
if (isRtlLayout(view)) {
setLayoutDirectionalMargins(view, (int) marginEnd, (int) marginStart);
} else {
setLayoutDirectionalMargins(view, (int) marginStart, (int) marginEnd);
}
view.requestLayout();
}
}

private static void setLayoutDirectionalMargins(
@NonNull View view,
int marginStart,
int marginEnd
) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.setMargins(marginStart, params.topMargin, marginEnd, params.bottomMargin);
}

/** Used to set a margin-top for views. */
@BindingAdapter("app:layoutMarginTop")
public static void setLayoutMarginTop(@NonNull View view, float marginTop) {
if (view.getLayoutParams() instanceof MarginLayoutParams) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.topMargin = (int) marginTop;
params.setMargins(
params.getMarginStart(),
(int) marginTop,
params.getMarginEnd(),
params.bottomMargin
);
view.requestLayout();
}
}
Expand All @@ -44,7 +68,12 @@ public static void setLayoutMarginTop(@NonNull View view, float marginTop) {
public static void setLayoutMarginBottom(@NonNull View view, float marginBottom) {
if (view.getLayoutParams() instanceof MarginLayoutParams) {
MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
params.bottomMargin = (int) marginBottom;
params.setMargins(
params.getMarginStart(),
params.topMargin,
params.getMarginEnd(),
(int) marginBottom
);
view.requestLayout();
}
}
Expand All @@ -63,4 +92,8 @@ public static void setLayoutMargin(@NonNull View view, float margin) {
view.requestLayout();
}
}

private static boolean isRtlLayout(View view) {
return ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_RTL;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package org.oppia.android.app.home.recentlyplayed

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import org.oppia.android.databinding.RecentlyPlayedStoryCardBinding
import org.oppia.android.databinding.SectionTitleBinding

private const val VIEW_TYPE_SECTION_TITLE_TEXT = 1
private const val VIEW_TYPE_SECTION_STORY_ITEM = 2

/**
* Adapter to inflate different items/views inside [RecyclerView] for Ongoing Story List.
*
* @property itemList the items that may be displayed in [RecentlyPlayedFragment]'s recycler view
*/
class PromotedStoryListAdapter(
private val itemList: MutableList<RecentlyPlayedItemViewModel>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

private var titleIndex: Int = 0
private var storyGridPosition: Int = 0
private var spanCount = 0

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
// TODO(#632): Generalize this binding to make adding future items easier.
VIEW_TYPE_SECTION_TITLE_TEXT -> {
val inflater = LayoutInflater.from(parent.context)
val binding =
SectionTitleBinding.inflate(
inflater,
parent,
/* attachToParent= */ false
)
SectionTitleViewHolder(binding)
}
VIEW_TYPE_SECTION_STORY_ITEM -> {
val inflater = LayoutInflater.from(parent.context)
val binding =
RecentlyPlayedStoryCardBinding.inflate(
inflater,
parent,
/* attachToParent= */ false
)
PromotedStoryViewHolder(binding)
}
else -> throw IllegalArgumentException("Invalid view type: $viewType")
}
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) =
when (holder.itemViewType) {
VIEW_TYPE_SECTION_TITLE_TEXT -> {
titleIndex = position
(holder as SectionTitleViewHolder).bind(itemList[position] as SectionTitleViewModel)
}
VIEW_TYPE_SECTION_STORY_ITEM -> {
storyGridPosition = position - titleIndex
(holder as PromotedStoryViewHolder).bind(itemList[position] as PromotedStoryViewModel)
}
else -> throw IllegalArgumentException("Invalid item view type: ${holder.itemViewType}")
}

override fun getItemViewType(position: Int): Int {
return when (itemList[position]) {
is SectionTitleViewModel -> {
VIEW_TYPE_SECTION_TITLE_TEXT
}
is PromotedStoryViewModel -> {
VIEW_TYPE_SECTION_STORY_ITEM
}
else -> throw IllegalArgumentException(
"Invalid type of data $position with item ${itemList[position]}"
)
}
}

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

/**
* Specifies the number of columns of recently played stories shown in the recently played stories
* list.
*
* @param spanCount specifies the number of spaces this item should occupy, based on screen size
*/
fun setSpanCount(spanCount: Int) {
this.spanCount = spanCount
}

private class SectionTitleViewHolder(
val binding: SectionTitleBinding
) : RecyclerView.ViewHolder(binding.root) {
/** Binds the view model that sets section titles. */
fun bind(sectionTitleViewModel: SectionTitleViewModel) {
binding.viewModel = sectionTitleViewModel
}
}

private class PromotedStoryViewHolder(
val binding: RecentlyPlayedStoryCardBinding
) : RecyclerView.ViewHolder(binding.root) {
/** Binds the view model that sets recently played items. */
fun bind(promotedStoryViewModel: PromotedStoryViewModel) {
binding.viewModel = promotedStoryViewModel
}
}
}
Loading