mirror of
https://github.com/MinimalBible/MinimalBible
synced 2024-11-05 07:38:20 -05:00
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.
This commit is contained in:
parent
c70c258231
commit
07015fc2ba
@ -23,6 +23,8 @@ import javax.inject.Named;
|
|||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.InjectView;
|
import butterknife.InjectView;
|
||||||
import dagger.ObjectGraph;
|
import dagger.ObjectGraph;
|
||||||
|
import rx.functions.Action1;
|
||||||
|
import rx.subjects.PublishSubject;
|
||||||
|
|
||||||
public class BibleViewer extends BaseActivity implements Injector {
|
public class BibleViewer extends BaseActivity implements Injector {
|
||||||
|
|
||||||
@ -33,6 +35,9 @@ public class BibleViewer extends BaseActivity implements Injector {
|
|||||||
@Inject
|
@Inject
|
||||||
BibleViewerPreferences prefs;
|
BibleViewerPreferences prefs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
PublishSubject<BookScrollEvent> scrollEventPublisher;
|
||||||
|
|
||||||
@InjectView(R.id.navigation_drawer)
|
@InjectView(R.id.navigation_drawer)
|
||||||
BibleMenu bibleMenu;
|
BibleMenu bibleMenu;
|
||||||
|
|
||||||
@ -101,10 +106,29 @@ public class BibleViewer extends BaseActivity implements Injector {
|
|||||||
|
|
||||||
setInsetToolbar(toolbar);
|
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);
|
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<BookScrollEvent>() {
|
||||||
|
@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);
|
bibleContent.setBook(mainBook, prefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void closeMenu() {
|
||||||
|
drawerLayout.closeDrawers();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
getMenuInflater().inflate(R.menu.viewer, menu);
|
getMenuInflater().inflate(R.menu.viewer, menu);
|
||||||
|
@ -16,6 +16,7 @@ import dagger.Provides;
|
|||||||
import de.devland.esperandro.Esperandro;
|
import de.devland.esperandro.Esperandro;
|
||||||
import rx.functions.Action1;
|
import rx.functions.Action1;
|
||||||
import rx.functions.Func1;
|
import rx.functions.Func1;
|
||||||
|
import rx.subjects.PublishSubject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modules used for the BibleViewer activity
|
* Modules used for the BibleViewer activity
|
||||||
@ -92,4 +93,10 @@ public class BibleViewerModules {
|
|||||||
BookManager bookManager() {
|
BookManager bookManager() {
|
||||||
return new BookManager();
|
return new BookManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
PublishSubject<BookScrollEvent> scrollEventPublisher() {
|
||||||
|
return PublishSubject.create();
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,9 +20,11 @@ import android.util.AttributeSet
|
|||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import org.bspeice.minimalbible.activity.setInset
|
import org.bspeice.minimalbible.activity.setInset
|
||||||
import android.support.annotation.LayoutRes
|
import android.support.annotation.LayoutRes
|
||||||
|
import org.crosswire.jsword.versification.BibleBook
|
||||||
|
|
||||||
class BibleMenu(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
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<BookScrollEvent> by Delegates.notNull();
|
||||||
|
|
||||||
{
|
{
|
||||||
val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
|
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
|
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)
|
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,
|
* TODO: Refactor this so the math parts are separate from the actual override functions,
|
||||||
* so it's easier to test.
|
* so it's easier to test.
|
||||||
*/
|
*/
|
||||||
class BibleAdapter(val b: Book) : BaseExpandableListAdapter() {
|
class BibleAdapter(val b: Book, val scrollPublisher: PublishSubject<BookScrollEvent>)
|
||||||
|
: BaseExpandableListAdapter() {
|
||||||
|
|
||||||
// Map BibleBooks to the number of chapters they have
|
// Map BibleBooks to the number of chapters they have
|
||||||
val menuMappings = b.getVersification().getBooks().map {
|
val menuMappings = b.getVersification().getBooks().map {
|
||||||
Pair(it, b.getVersification().getLastChapter(it))
|
Pair(it, b.getVersification().getLastChapter(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun getGroupIdForBook(b: BibleBook) = menuMappings.indexOf(
|
||||||
* The listener that should be registered to receive click events
|
menuMappings.first { it.first == b }
|
||||||
* It's created here because we need access to the menuMappings
|
)
|
||||||
*/
|
|
||||||
fun getMenuClickListener(listener: PublishSubject<BookScrollEvent>) =
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var groupHighlighted: Int = 0
|
var groupHighlighted: Int = 0
|
||||||
var childHighlighted: Int = 0
|
var childHighlighted: Int = 0
|
||||||
@ -129,7 +124,9 @@ class BibleAdapter(val b: Book) : BaseExpandableListAdapter() {
|
|||||||
chapterStart + 2
|
chapterStart + 2
|
||||||
val view = ChildItemHolder.init(
|
val view = ChildItemHolder.init(
|
||||||
getOrInflate(convertView, parent, R.layout.list_bible_menu_child),
|
getOrInflate(convertView, parent, R.layout.list_bible_menu_child),
|
||||||
chapterStart..chapterEnd
|
chapterStart..chapterEnd,
|
||||||
|
menuMappings[group].first,
|
||||||
|
scrollPublisher
|
||||||
)
|
)
|
||||||
|
|
||||||
return view
|
return view
|
||||||
@ -170,16 +167,18 @@ class GroupItemHolder(val bindTo: View) {
|
|||||||
* Bind the child items. There are some funky math things going on since
|
* 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
|
* 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<BookScrollEvent>) {
|
||||||
val content1 = bindTo.findViewById(R.id.content1) as TextView
|
val content1 = bindTo.findViewById(R.id.content1) as TextView
|
||||||
val content2 = bindTo.findViewById(R.id.content2) as TextView
|
val content2 = bindTo.findViewById(R.id.content2) as TextView
|
||||||
val content3 = bindTo.findViewById(R.id.content3) as TextView
|
val content3 = bindTo.findViewById(R.id.content3) as TextView
|
||||||
|
|
||||||
class object {
|
class object {
|
||||||
fun init(v: View, obj: IntRange): View {
|
fun init(v: View, obj: IntRange, book: BibleBook,
|
||||||
|
scrollPublisher: PublishSubject<BookScrollEvent>): View {
|
||||||
val holder =
|
val holder =
|
||||||
if (v.getTag() != null) v.getTag() as ChildItemHolder
|
if (v.getTag() != null) v.getTag() as ChildItemHolder
|
||||||
else ChildItemHolder(v)
|
else ChildItemHolder(v, book, scrollPublisher)
|
||||||
|
|
||||||
holder.clearViews()
|
holder.clearViews()
|
||||||
holder.bind(obj)
|
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
|
// 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,
|
// as a result of recycling. There should probably be a different way of doing this,
|
||||||
// but get something that works first.
|
// 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
|
* Set up the view with the data we want to display
|
||||||
*/
|
*/
|
||||||
fun bind(range: IntRange) = range.forEach {
|
fun bind(range: IntRange) = range.forEach {
|
||||||
getViewForPosition(it) setText it.toString()
|
val view = getViewForPosition(it)
|
||||||
|
view setText it.toString()
|
||||||
|
view setOnClickListener buildOnClickListener(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,19 +22,23 @@ import android.support.v7.widget.LinearLayoutManager
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
|
||||||
class BibleView(val ctx: Context, val attrs: AttributeSet) : LinearLayout(ctx, attrs) {
|
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<BookScrollEvent> 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)
|
val rootView = inflater.inflate(R.layout.view_bible, this, true)
|
||||||
|
|
||||||
bibleContent = rootView.findViewById(R.id.bible_content) as RecyclerView
|
bibleContent = rootView.findViewById(R.id.bible_content) as RecyclerView
|
||||||
bibleContent setLayoutManager LinearLayoutManager(ctx)
|
bibleContent setLayoutManager layoutManager
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setBook(b: Book, prefs: BibleViewerPreferences) {
|
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
|
override fun getItemCount(): Int = chapterCount
|
||||||
|
|
||||||
fun bindScrollHandler(provider: PublishSubject<BookScrollEvent>,
|
public fun bindScrollHandler(provider: PublishSubject<BookScrollEvent>,
|
||||||
lM: RecyclerView.LayoutManager) {
|
lM: RecyclerView.LayoutManager) {
|
||||||
provider subscribe {
|
provider subscribe {
|
||||||
val event = it
|
val event = it
|
||||||
|
Loading…
Reference in New Issue
Block a user