rewrite the layout to a viewpager split to contacts and favorites

This commit is contained in:
tibbi 2017-12-28 23:59:49 +01:00
parent 74064e57d5
commit 1e0d8f383d
11 changed files with 423 additions and 157 deletions

View File

@ -36,7 +36,7 @@ ext {
}
dependencies {
implementation 'com.simplemobiletools:commons:3.4.14'
implementation 'com.simplemobiletools:commons:3.4.15'
implementation 'joda-time:joda-time:2.9.9'
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"

View File

@ -1,45 +1,43 @@
package com.simplemobiletools.contacts.activities
import android.content.Intent
import android.graphics.Paint
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.contacts.BuildConfig
import com.simplemobiletools.contacts.R
import com.simplemobiletools.contacts.adapters.ContactsAdapter
import com.simplemobiletools.contacts.adapters.ViewPagerAdapter
import com.simplemobiletools.contacts.dialogs.ChangeSortingDialog
import com.simplemobiletools.contacts.dialogs.FilterContactSourcesDialog
import com.simplemobiletools.contacts.extensions.config
import com.simplemobiletools.contacts.extensions.openContact
import com.simplemobiletools.contacts.extensions.tryStartCall
import com.simplemobiletools.contacts.helpers.ContactsHelper
import com.simplemobiletools.contacts.models.Contact
import com.simplemobiletools.contacts.extensions.onPageChanged
import com.simplemobiletools.contacts.extensions.onTabSelectionChanged
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_contacts.*
import kotlinx.android.synthetic.main.fragment_favorites.*
class MainActivity : SimpleActivity() {
private var isFirstResume = true
class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private var storedUseEnglish = false
private var storedTextColor = 0
private var storedBackgroundColor = 0
private var storedPrimaryColor = 0
private var storedStartNameWithSurname = false
private var isFirstResume = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
appLaunched()
contacts_fab.setOnClickListener { addNewContact() }
handlePermission(PERMISSION_READ_CONTACTS) {
if (it) {
handlePermission(PERMISSION_WRITE_CONTACTS) {
if (it) {
initContacts()
initFragments()
} else {
toast(R.string.no_contacts_permission)
finish()
@ -50,7 +48,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
finish()
}
}
storeStateVariables()
}
@ -61,37 +58,37 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
return
}
if (storedTextColor != config.textColor) {
(contacts_list.adapter as ContactsAdapter).apply {
updateTextColor(config.textColor)
initDrawables()
}
val configTextColor = config.textColor
if (storedTextColor != configTextColor) {
val inactiveTabIndex = if (viewpager.currentItem == 0) 1 else 0
main_tabs_holder.getTabAt(inactiveTabIndex)?.icon?.applyColorFilter(configTextColor)
contacts_fragment.textColorChanged(configTextColor)
favorites_fragment.textColorChanged(configTextColor)
}
if (storedPrimaryColor != config.primaryColor) {
contacts_fastscroller.updatePrimaryColor()
val configBackgroundColor = config.backgroundColor
if (storedBackgroundColor != configBackgroundColor) {
main_tabs_holder.background = ColorDrawable(configBackgroundColor)
}
if (storedStartNameWithSurname != config.startNameWithSurname) {
(contacts_list.adapter as ContactsAdapter).apply {
startNameWithSurname = config.startNameWithSurname
config.sorting = if (config.startNameWithSurname) SORT_BY_SURNAME else SORT_BY_FIRST_NAME
initContacts()
}
val configPrimaryColor = config.primaryColor
if (storedPrimaryColor != configPrimaryColor) {
main_tabs_holder.setSelectedTabIndicatorColor(getAdjustedPrimaryColor())
main_tabs_holder.getTabAt(viewpager.currentItem)?.icon?.applyColorFilter(getAdjustedPrimaryColor())
contacts_fragment.primaryColorChanged(configPrimaryColor)
favorites_fragment.primaryColorChanged(configPrimaryColor)
}
contacts_fastscroller.updateBubbleColors()
contacts_fastscroller.allowBubbleDisplay = config.showInfoBubble
updateTextColors(contacts_holder)
contacts_placeholder_2.paintFlags = contacts_placeholder_2.paintFlags or Paint.UNDERLINE_TEXT_FLAG
contacts_placeholder_2.setTextColor(config.primaryColor)
contacts_placeholder_2.setOnClickListener {
showFilterDialog()
val configStartNameWithSurname = config.startNameWithSurname
if (storedStartNameWithSurname != configStartNameWithSurname) {
contacts_fragment.startNameWithSurnameChanged(configStartNameWithSurname)
favorites_fragment.startNameWithSurnameChanged(configStartNameWithSurname)
}
if (!isFirstResume) {
initContacts()
contacts_fragment.initContacts()
contacts_fragment.onActivityResume()
favorites_fragment.onActivityResume()
}
isFirstResume = false
}
@ -117,22 +114,6 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
return true
}
private fun showSortingDialog() {
ChangeSortingDialog(this) {
initContacts()
}
}
private fun showFilterDialog() {
FilterContactSourcesDialog(this) {
initContacts()
}
}
private fun launchAbout() {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT or LICENSE_JODA or LICENSE_GLIDE, BuildConfig.VERSION_NAME)
}
private fun storeStateVariables() {
config.apply {
storedUseEnglish = useEnglish
@ -143,63 +124,44 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
}
}
private fun initContacts() {
ContactsHelper(this).getContacts {
if (config.lastUsedContactSource.isEmpty()) {
val grouped = it.groupBy { it.source }.maxWith(compareBy { it.value.size })
config.lastUsedContactSource = grouped?.key ?: ""
}
private fun initFragments() {
viewpager.adapter = ViewPagerAdapter(this)
viewpager.onPageChanged {
main_tabs_holder.getTabAt(it)?.select()
invalidateOptionsMenu()
}
Contact.sorting = config.sorting
it.sort()
main_tabs_holder.apply {
background = ColorDrawable(config.backgroundColor)
setSelectedTabIndicatorColor(getAdjustedPrimaryColor())
getTabAt(0)?.icon?.applyColorFilter(getAdjustedPrimaryColor())
getTabAt(1)?.icon?.applyColorFilter(config.textColor)
}
if (it.hashCode() != (contacts_list.adapter as? ContactsAdapter)?.contactItems?.hashCode()) {
runOnUiThread {
setupContacts(it)
main_tabs_holder.onTabSelectionChanged(
tabUnselectedAction = {
it.icon?.applyColorFilter(config.textColor)
},
tabSelectedAction = {
viewpager.currentItem = it.position
it.icon?.applyColorFilter(getAdjustedPrimaryColor())
}
}
)
}
private fun showSortingDialog() {
ChangeSortingDialog(this) {
contacts_fragment.initContacts()
}
}
private fun setupContacts(contacts: ArrayList<Contact>) {
contacts_placeholder_2.beVisibleIf(contacts.isEmpty())
contacts_placeholder.beVisibleIf(contacts.isEmpty())
val currAdapter = contacts_list.adapter
if (currAdapter == null) {
ContactsAdapter(this, contacts, this, contacts_list) {
if (config.callContact) {
val contact = it as Contact
if (contact.phoneNumbers.isNotEmpty()) {
tryStartCall(it)
} else {
toast(R.string.no_phone_number_found)
}
} else {
openContact(it as Contact)
}
}.apply {
setupDragListener(true)
addVerticalDividers(true)
contacts_list.adapter = this
}
contacts_fastscroller.setViews(contacts_list) {
val item = (contacts_list.adapter as ContactsAdapter).contactItems.getOrNull(it)
contacts_fastscroller.updateBubbleText(item?.getBubbleText() ?: "")
}
} else {
(currAdapter as ContactsAdapter).updateItems(contacts)
fun showFilterDialog() {
FilterContactSourcesDialog(this) {
contacts_fragment.initContacts()
}
}
private fun addNewContact() {
Intent(applicationContext, ContactActivity::class.java).apply {
startActivity(this)
}
}
override fun refreshItems() {
initContacts()
private fun launchAbout() {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT or LICENSE_JODA or LICENSE_GLIDE, BuildConfig.VERSION_NAME)
}
}

View File

@ -0,0 +1,26 @@
package com.simplemobiletools.contacts.adapters
import android.support.v4.view.PagerAdapter
import android.view.View
import android.view.ViewGroup
import com.simplemobiletools.contacts.R
import com.simplemobiletools.contacts.activities.MainActivity
import com.simplemobiletools.contacts.fragments.MyViewPagerFragment
class ViewPagerAdapter(val activity: MainActivity) : PagerAdapter() {
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val layout = if (position == 0) R.layout.fragment_contacts else R.layout.fragment_favorites
val view = activity.layoutInflater.inflate(layout, container, false)
container.addView(view)
(view as MyViewPagerFragment).setupFragment(activity)
return view
}
override fun destroyItem(container: ViewGroup, position: Int, item: Any) {
container.removeView(item as View)
}
override fun getCount() = 2
override fun isViewFromObject(view: View, item: Any) = view == item
}

View File

@ -0,0 +1,17 @@
package com.simplemobiletools.contacts.extensions
import android.support.design.widget.TabLayout
fun TabLayout.onTabSelectionChanged(tabUnselectedAction: (inactiveTab: TabLayout.Tab) -> Unit, tabSelectedAction: (activeTab: TabLayout.Tab) -> Unit) =
setOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
tabSelectedAction(tab)
}
override fun onTabUnselected(tab: TabLayout.Tab) {
tabUnselectedAction(tab)
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})

View File

@ -0,0 +1,16 @@
package com.simplemobiletools.contacts.extensions
import android.support.v4.view.ViewPager
fun ViewPager.onPageChanged(pageChangedAction: (activePage: Int) -> Unit) =
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageSelected(position: Int) {
pageChangedAction(position)
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
}
override fun onPageScrollStateChanged(state: Int) {
}
})

View File

@ -0,0 +1,147 @@
package com.simplemobiletools.contacts.fragments
import android.content.Context
import android.content.Intent
import android.graphics.Paint
import android.util.AttributeSet
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.isActivityDestroyed
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.SORT_BY_FIRST_NAME
import com.simplemobiletools.commons.helpers.SORT_BY_SURNAME
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.contacts.R
import com.simplemobiletools.contacts.activities.ContactActivity
import com.simplemobiletools.contacts.activities.MainActivity
import com.simplemobiletools.contacts.activities.SimpleActivity
import com.simplemobiletools.contacts.adapters.ContactsAdapter
import com.simplemobiletools.contacts.extensions.openContact
import com.simplemobiletools.contacts.extensions.tryStartCall
import com.simplemobiletools.contacts.helpers.ContactsHelper
import com.simplemobiletools.contacts.models.Contact
import kotlinx.android.synthetic.main.fragment_contacts.view.*
class ContactsFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet), RefreshRecyclerViewListener {
var activity: MainActivity? = null
override fun initFragment(activity: MainActivity) {
if (this.activity == null) {
this.activity = activity
contacts_fab.setOnClickListener {
addNewContact()
}
contacts_placeholder_2.setOnClickListener {
activity.showFilterDialog()
}
contacts_placeholder_2.paintFlags = contacts_placeholder_2.paintFlags or Paint.UNDERLINE_TEXT_FLAG
updateViewStuff()
}
initContacts()
}
override fun textColorChanged(color: Int) {
(contacts_list.adapter as ContactsAdapter).apply {
updateTextColor(color)
initDrawables()
}
}
override fun primaryColorChanged(color: Int) {
contacts_fastscroller.updatePrimaryColor()
contacts_fab.setColors(config.textColor, color, config.backgroundColor)
contacts_fastscroller.updateBubblePrimaryColor()
}
override fun startNameWithSurnameChanged(startNameWithSurname: Boolean) {
(contacts_list.adapter as ContactsAdapter).apply {
config.sorting = if (startNameWithSurname) SORT_BY_SURNAME else SORT_BY_FIRST_NAME
initContacts()
}
}
override fun onActivityResume() {
updateViewStuff()
}
private fun updateViewStuff() {
context.updateTextColors(contacts_fragment)
contacts_fastscroller.updateBubbleColors()
contacts_fastscroller.allowBubbleDisplay = config.showInfoBubble
contacts_placeholder_2.setTextColor(config.primaryColor)
}
fun initContacts() {
if (activity == null || activity!!.isActivityDestroyed()) {
return
}
ContactsHelper(activity!!).getContacts {
if (activity == null || activity!!.isActivityDestroyed()) {
return@getContacts
}
if (config.lastUsedContactSource.isEmpty()) {
val grouped = it.groupBy { it.source }.maxWith(compareBy { it.value.size })
config.lastUsedContactSource = grouped?.key ?: ""
}
Contact.sorting = config.sorting
it.sort()
if (it.hashCode() != (contacts_list.adapter as? ContactsAdapter)?.contactItems?.hashCode()) {
activity!!.runOnUiThread {
setupContacts(it)
}
}
}
}
private fun setupContacts(contacts: ArrayList<Contact>) {
contacts_placeholder_2.beVisibleIf(contacts.isEmpty())
contacts_placeholder.beVisibleIf(contacts.isEmpty())
val currAdapter = contacts_list.adapter
if (currAdapter == null) {
ContactsAdapter(activity as SimpleActivity, contacts, this, contacts_list) {
if (config.callContact) {
val contact = it as Contact
if (contact.phoneNumbers.isNotEmpty()) {
(activity as SimpleActivity).tryStartCall(it)
} else {
activity!!.toast(R.string.no_phone_number_found)
}
} else {
context!!.openContact(it as Contact)
}
}.apply {
setupDragListener(true)
addVerticalDividers(true)
contacts_list.adapter = this
}
contacts_fastscroller.setViews(contacts_list) {
val item = (contacts_list.adapter as ContactsAdapter).contactItems.getOrNull(it)
contacts_fastscroller.updateBubbleText(item?.getBubbleText() ?: "")
}
} else {
(currAdapter as ContactsAdapter).apply {
startNameWithSurname = config.startNameWithSurname
updateItems(contacts)
}
}
}
private fun addNewContact() {
Intent(context, ContactActivity::class.java).apply {
context.startActivity(this)
}
}
override fun refreshItems() {
initContacts()
}
}

View File

@ -0,0 +1,22 @@
package com.simplemobiletools.contacts.fragments
import android.content.Context
import android.util.AttributeSet
import com.simplemobiletools.contacts.activities.MainActivity
class FavoritesFragment(context: Context, attributeSet: AttributeSet) : MyViewPagerFragment(context, attributeSet) {
override fun initFragment(activity: MainActivity) {
}
override fun textColorChanged(color: Int) {
}
override fun primaryColorChanged(color: Int) {
}
override fun startNameWithSurnameChanged(startNameWithSurname: Boolean) {
}
override fun onActivityResume() {
}
}

View File

@ -0,0 +1,27 @@
package com.simplemobiletools.contacts.fragments
import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.util.AttributeSet
import com.simplemobiletools.contacts.activities.MainActivity
import com.simplemobiletools.contacts.extensions.config
import com.simplemobiletools.contacts.helpers.Config
abstract class MyViewPagerFragment(context: Context, attributeSet: AttributeSet) : CoordinatorLayout(context, attributeSet) {
lateinit var config: Config
fun setupFragment(activity: MainActivity) {
config = activity.config
initFragment(activity)
}
abstract fun initFragment(activity: MainActivity)
abstract fun textColorChanged(color: Int)
abstract fun primaryColorChanged(color: Int)
abstract fun startNameWithSurnameChanged(startNameWithSurname: Boolean)
abstract fun onActivityResume()
}

View File

@ -1,68 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/contacts_holder"
xmlns:tooLs="http://schemas.android.com/tools"
android:id="@+id/main_holder"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
tooLs:ignore="MissingPrefix">
<RelativeLayout
android:id="@+id/contacts_wrapper"
<android.support.design.widget.TabLayout
android:id="@+id/main_tabs_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="48dp"
app:elevation="6dp"
app:tabIndicatorColor="@android:color/white"
app:tabIndicatorHeight="2dp"
app:tabMinWidth="150dp"
app:tabSelectedTextColor="@android:color/white">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/contacts_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/activity_margin"
android:gravity="center"
android:text="@string/no_items_found"
android:textSize="@dimen/bigger_text_size"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/contacts_placeholder_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/contacts_placeholder"
android:layout_centerHorizontal="true"
android:gravity="center"
android:paddingBottom="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin"
android:text="@string/change_filter"
android:textSize="@dimen/bigger_text_size"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/contacts_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbars="none"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<com.simplemobiletools.commons.views.FastScroller
android:id="@+id/contacts_fastscroller"
<android.support.design.widget.TabItem
android:id="@+id/tab_contacts"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:paddingLeft="@dimen/normal_margin"
android:paddingStart="@dimen/normal_margin">
android:layout_height="wrap_content"
android:icon="@drawable/ic_person"/>
<include layout="@layout/fastscroller_handle_vertical"/>
<android.support.design.widget.TabItem
android:id="@+id/tab_favorites"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:icon="@drawable/ic_star_on"/>
</com.simplemobiletools.commons.views.FastScroller>
</RelativeLayout>
</android.support.design.widget.TabLayout>
<com.simplemobiletools.commons.views.MyFloatingActionButton
android:id="@+id/contacts_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/activity_margin"
android:src="@drawable/ic_plus"/>
<com.booking.rtlviewpager.RtlViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/main_tabs_holder"/>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<com.simplemobiletools.contacts.fragments.ContactsFragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/contacts_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/contacts_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/contacts_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/activity_margin"
android:gravity="center"
android:text="@string/no_items_found"
android:textSize="@dimen/bigger_text_size"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/contacts_placeholder_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/contacts_placeholder"
android:layout_centerHorizontal="true"
android:gravity="center"
android:paddingBottom="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin"
android:text="@string/change_filter"
android:textSize="@dimen/bigger_text_size"
android:visibility="gone"/>
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/contacts_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbars="none"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<com.simplemobiletools.commons.views.FastScroller
android:id="@+id/contacts_fastscroller"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:paddingLeft="@dimen/normal_margin"
android:paddingStart="@dimen/normal_margin">
<include layout="@layout/fastscroller_handle_vertical"/>
</com.simplemobiletools.commons.views.FastScroller>
</RelativeLayout>
<com.simplemobiletools.commons.views.MyFloatingActionButton
android:id="@+id/contacts_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/activity_margin"
android:src="@drawable/ic_plus"/>
</com.simplemobiletools.contacts.fragments.ContactsFragment>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<com.simplemobiletools.contacts.fragments.FavoritesFragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/favorites_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.simplemobiletools.contacts.fragments.FavoritesFragment>