From 07015fc2babe97476d145b1485acf6893def1632 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Mon, 29 Dec 2014 01:27:10 -0500 Subject: [PATCH] Everything now responds to scroll events correctly! Time for another release shortly, need to add some testing code and likely do some quick refactor work. Pretty happy where everything's at though, honestly. --- .../activity/viewer/BibleViewer.java | 24 +++++++++ .../activity/viewer/BibleViewerModules.java | 7 +++ .../minimalbible/activity/viewer/BibleMenu.kt | 54 ++++++++++--------- .../minimalbible/activity/viewer/BibleView.kt | 16 +++--- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewer.java b/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewer.java index b424738..21eeac0 100644 --- a/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewer.java +++ b/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewer.java @@ -23,6 +23,8 @@ import javax.inject.Named; import butterknife.ButterKnife; import butterknife.InjectView; import dagger.ObjectGraph; +import rx.functions.Action1; +import rx.subjects.PublishSubject; public class BibleViewer extends BaseActivity implements Injector { @@ -33,6 +35,9 @@ public class BibleViewer extends BaseActivity implements Injector { @Inject BibleViewerPreferences prefs; + @Inject + PublishSubject scrollEventPublisher; + @InjectView(R.id.navigation_drawer) BibleMenu bibleMenu; @@ -101,10 +106,29 @@ public class BibleViewer extends BaseActivity implements Injector { setInsetToolbar(toolbar); + // Currently you must set up the menu in exactly this order. Do I need to refactor this? + bibleMenu.setScrollEventPublisher(scrollEventPublisher); bibleMenu.setBible(mainBook); + + // If a new chapter is selected, make sure we close the drawer + // We can't specify `this` as the subscriber since we can't + // extend Action1 + scrollEventPublisher.subscribe(new Action1() { + @Override + public void call(BookScrollEvent bookScrollEvent) { + closeMenu(); + } + }); + + // Set up the view to respond to scroll events as well. Again, exact order is needed. + bibleContent.setScrollPublisher(scrollEventPublisher); bibleContent.setBook(mainBook, prefs); } + public void closeMenu() { + drawerLayout.closeDrawers(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.viewer, menu); diff --git a/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewerModules.java b/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewerModules.java index a1154d3..7dd605a 100644 --- a/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewerModules.java +++ b/app/src/main/java/org/bspeice/minimalbible/activity/viewer/BibleViewerModules.java @@ -16,6 +16,7 @@ import dagger.Provides; import de.devland.esperandro.Esperandro; import rx.functions.Action1; import rx.functions.Func1; +import rx.subjects.PublishSubject; /** * Modules used for the BibleViewer activity @@ -92,4 +93,10 @@ public class BibleViewerModules { BookManager bookManager() { return new BookManager(); } + + @Provides + @Singleton + PublishSubject scrollEventPublisher() { + return PublishSubject.create(); + } } \ No newline at end of file diff --git a/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleMenu.kt b/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleMenu.kt index 5486a01..ebe0900 100644 --- a/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleMenu.kt +++ b/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleMenu.kt @@ -20,9 +20,11 @@ import android.util.AttributeSet import kotlin.properties.Delegates import org.bspeice.minimalbible.activity.setInset import android.support.annotation.LayoutRes +import org.crosswire.jsword.versification.BibleBook class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) { - var menuContent: ExpandableListView by Delegates.notNull(); + var menuContent: ExpandableListView by Delegates.notNull() + var scrollEventPublisher: PublishSubject by Delegates.notNull(); { val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater @@ -31,7 +33,13 @@ class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, a menuContent = findViewById(R.id._bible_menu) as ExpandableListView } - fun setBible(b: Book) = menuContent.setAdapter(BibleAdapter(b)) + fun setBible(b: Book) { + val adapter = BibleAdapter(b, scrollEventPublisher) + menuContent setAdapter adapter + scrollEventPublisher subscribe { + menuContent.collapseGroup(adapter.getGroupIdForBook(it.b)) + } + } fun placeInset(a: Activity) = setInset(a) } @@ -48,30 +56,17 @@ class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, a * TODO: Refactor this so the math parts are separate from the actual override functions, * so it's easier to test. */ -class BibleAdapter(val b: Book) : BaseExpandableListAdapter() { +class BibleAdapter(val b: Book, val scrollPublisher: PublishSubject) +: BaseExpandableListAdapter() { // Map BibleBooks to the number of chapters they have val menuMappings = b.getVersification().getBooks().map { Pair(it, b.getVersification().getLastChapter(it)) } - /** - * The listener that should be registered to receive click events - * It's created here because we need access to the menuMappings - */ - fun getMenuClickListener(listener: PublishSubject) = - object : ExpandableListView.OnChildClickListener { - override fun onChildClick(listView: ExpandableListView?, childView: View?, - groupPosition: Int, childPosition: Int, id: Long): Boolean { - - val map = menuMappings[groupPosition] - // childPosition is index-based - // TODO: Figure out why trying chapter 0 triggers a NotImplementedException... - listener onNext BookScrollEvent(map.first, childPosition + 1) - - return true; // Event was handled - } - } + fun getGroupIdForBook(b: BibleBook) = menuMappings.indexOf( + menuMappings.first { it.first == b } + ) var groupHighlighted: Int = 0 var childHighlighted: Int = 0 @@ -129,7 +124,9 @@ class BibleAdapter(val b: Book) : BaseExpandableListAdapter() { chapterStart + 2 val view = ChildItemHolder.init( getOrInflate(convertView, parent, R.layout.list_bible_menu_child), - chapterStart..chapterEnd + chapterStart..chapterEnd, + menuMappings[group].first, + scrollPublisher ) return view @@ -170,16 +167,18 @@ class GroupItemHolder(val bindTo: View) { * Bind the child items. There are some funky math things going on since * we display three chapters per row, check the adapter for more documentation */ -class ChildItemHolder(val bindTo: View) { +class ChildItemHolder(val bindTo: View, val book: BibleBook, + val scrollPublisher: PublishSubject) { val content1 = bindTo.findViewById(R.id.content1) as TextView val content2 = bindTo.findViewById(R.id.content2) as TextView val content3 = bindTo.findViewById(R.id.content3) as TextView class object { - fun init(v: View, obj: IntRange): View { + fun init(v: View, obj: IntRange, book: BibleBook, + scrollPublisher: PublishSubject): View { val holder = if (v.getTag() != null) v.getTag() as ChildItemHolder - else ChildItemHolder(v) + else ChildItemHolder(v, book, scrollPublisher) holder.clearViews() holder.bind(obj) @@ -187,6 +186,9 @@ class ChildItemHolder(val bindTo: View) { } } + fun buildOnClickListener(chapter: Int): View.OnClickListener = + View.OnClickListener { scrollPublisher onNext BookScrollEvent(book, chapter) } + // Clear the views before binding, so that we don't have stale text left // as a result of recycling. There should probably be a different way of doing this, // but get something that works first. @@ -211,6 +213,8 @@ class ChildItemHolder(val bindTo: View) { * Set up the view with the data we want to display */ fun bind(range: IntRange) = range.forEach { - getViewForPosition(it) setText it.toString() + val view = getViewForPosition(it) + view setText it.toString() + view setOnClickListener buildOnClickListener(it) } } diff --git a/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleView.kt b/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleView.kt index 05b5057..70a41d6 100644 --- a/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleView.kt +++ b/app/src/main/kotlin/org/bspeice/minimalbible/activity/viewer/BibleView.kt @@ -22,19 +22,23 @@ import android.support.v7.widget.LinearLayoutManager import android.widget.LinearLayout class BibleView(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) { - var bibleContent: RecyclerView by Delegates.notNull(); + var bibleContent: RecyclerView by Delegates.notNull() + var scrollPublisher: PublishSubject by Delegates.notNull() + + val layoutManager: LinearLayoutManager = LinearLayoutManager(ctx) + val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater; { - val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - // Don't attach yet, as we haven't finished setup val rootView = inflater.inflate(R.layout.view_bible, this, true) bibleContent = rootView.findViewById(R.id.bible_content) as RecyclerView - bibleContent setLayoutManager LinearLayoutManager(ctx) + bibleContent setLayoutManager layoutManager } fun setBook(b: Book, prefs: BibleViewerPreferences) { - bibleContent setAdapter BookAdapter(b, prefs) + val adapter = BookAdapter(b, prefs) + adapter.bindScrollHandler(scrollPublisher, layoutManager) + bibleContent setAdapter adapter } } @@ -114,7 +118,7 @@ class BookAdapter(val b: Book, val prefs: BibleViewerPreferences) */ override fun getItemCount(): Int = chapterCount - fun bindScrollHandler(provider: PublishSubject, + public fun bindScrollHandler(provider: PublishSubject, lM: RecyclerView.LayoutManager) { provider subscribe { val event = it