Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0969e614 authored by Nihar Thakkar's avatar Nihar Thakkar
Browse files

Redo categories UI

parent cae7b82d
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -26,10 +26,8 @@ import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
    private var currentFragmentId = 0
    private val homeFragment = HomeFragment()
    private val categoriesFragment = CategoriesFragment()
    private val searchFragment = SearchFragment()
    private val updatesFragment = UpdatesFragment()
    private val settingsFragment = SettingsFragment()
    private val installManagerGetter = InstallManagerGetter()

    override fun onCreate(savedInstanceState: Bundle?) {
@@ -83,7 +81,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
                return true
            }
            R.id.menu_categories -> {
                showFragment(categoriesFragment)
                showFragment(CategoriesFragment())
                return true
            }
            R.id.menu_search -> {
@@ -95,7 +93,7 @@ class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemS
                return true
            }
            R.id.menu_settings -> {
                showFragment(settingsFragment)
                showFragment(SettingsFragment())
                return true
            }
        }
+60 −0
Original line number Diff line number Diff line
package io.eelo.appinstaller.categories

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import io.eelo.appinstaller.R
import io.eelo.appinstaller.categories.viewmodel.CategoriesViewModel
import io.eelo.appinstaller.utils.Common
import kotlinx.android.synthetic.main.error_layout.view.*
import kotlinx.android.synthetic.main.fragment_application_categories.view.*

class ApplicationsFragment : Fragment() {
    private lateinit var categoriesViewModel: CategoriesViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        categoriesViewModel = ViewModelProviders.of(activity!!).get(CategoriesViewModel::class.java)

        val view = inflater.inflate(R.layout.fragment_application_categories, container, false)
        view.categories_list.layoutManager = LinearLayoutManager(context)

        view.categories_list.visibility = View.GONE
        view.progress_bar.visibility = View.VISIBLE
        view.error_container.visibility = View.GONE
        view.findViewById<TextView>(R.id.error_resolve).setOnClickListener {
            view.progress_bar.visibility = View.VISIBLE
            categoriesViewModel.loadCategories(context!!)
        }

        // Bind to the list of applications categories
        categoriesViewModel.getApplicationsCategories().observe(this, Observer {
            if (it!!.isNotEmpty()) {
                view.categories_list.adapter = CategoriesListAdapter(it)
                view.categories_list.visibility = View.VISIBLE
                view.progress_bar.visibility = View.GONE
            }
        })

        // Bind to the screen error
        categoriesViewModel.getScreenError().observe(this, Observer {
            if (it != null) {
                view.error_description.text = activity!!.getString(Common.getScreenErrorDescriptionId(it))
                view.error_container.visibility = View.VISIBLE
                view.progress_bar.visibility = View.GONE
            } else {
                view.error_container.visibility = View.GONE
            }
        })

        if (categoriesViewModel.getApplicationsCategories().value!!.isEmpty()) {
            categoriesViewModel.loadCategories(context!!)
        }
        return view
    }
}
+14 −148
Original line number Diff line number Diff line
package io.eelo.appinstaller.categories

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.content.res.Configuration
import android.os.Bundle
import android.support.design.widget.TabLayout
import android.support.v4.app.Fragment
import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.Gravity
import android.support.v4.view.ViewPager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import io.eelo.appinstaller.R
import io.eelo.appinstaller.categories.viewmodel.CategoriesViewModel
import io.eelo.appinstaller.utils.Common
import kotlin.math.roundToInt

class CategoriesFragment : Fragment() {

    private lateinit var categoriesViewModel: CategoriesViewModel
    private lateinit var applicationsCategoriesList: GridLayout
    private lateinit var gamesCategoriesList: GridLayout
    private lateinit var categoriesContainer: LinearLayout
    private lateinit var progressBar: ProgressBar
    private lateinit var itemParams: LinearLayout.LayoutParams
    private var itemWidth = 0
    private var itemPadding = 0
    private var itemMargin = 0

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_categories, container, false)
        val tabLayout = view.findViewById<TabLayout>(R.id.tab_layout)
        val viewPager = view.findViewById<ViewPager>(R.id.view_pager)

        categoriesViewModel = ViewModelProviders.of(activity!!).get(CategoriesViewModel::class.java)
        applicationsCategoriesList = view.findViewById(R.id.applications_categories_list)
        gamesCategoriesList = view.findViewById(R.id.games_categories_list)
        categoriesContainer = view.findViewById(R.id.categories_container)
        progressBar = view.findViewById(R.id.progress_bar)
        val errorContainer = view.findViewById<LinearLayout>(R.id.error_container)
        val errorDescription = view.findViewById<TextView>(R.id.error_description)

        // Initialise UI elements
        initialiseDimensions()
        handleDeviceOrientation()
        categoriesContainer.visibility = View.GONE
        progressBar.visibility = View.VISIBLE
        errorContainer.visibility = View.GONE
        view.findViewById<TextView>(R.id.error_resolve).setOnClickListener {
            progressBar.visibility = View.VISIBLE
            categoriesViewModel.loadCategories(context!!)
        }

        // Bind to the list of applications categories
        categoriesViewModel.getApplicationsCategories().observe(this, Observer {
            showApplicationsCategories()
        })

        // Bind to the list of games categories
        categoriesViewModel.getGamesCategories().observe(this, Observer {
            showGamesCategories()
        })

        // Bind to the screen error
        categoriesViewModel.getScreenError().observe(this, Observer {
            if (it != null) {
                errorDescription.text = activity!!.getString(Common.getScreenErrorDescriptionId(it))
                errorContainer.visibility = View.VISIBLE
                progressBar.visibility = View.GONE
            } else {
                errorContainer.visibility = View.GONE
            }
        })
        viewPager.adapter = CategoriesViewPagerAdapter(activity!!.supportFragmentManager, tabLayout.tabCount)
        viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))

        if (categoriesViewModel.getApplicationsCategories().value!!.isEmpty() ||
                categoriesViewModel.getGamesCategories().value!!.isEmpty()) {
            categoriesViewModel.loadCategories(context!!)
        }
        return view
        tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab) {
                viewPager.currentItem = tab.position
            }

    private fun initialiseDimensions() {
        // Do some math and figure out item width, padding and margin
        val metrics = DisplayMetrics()
        activity!!.windowManager.defaultDisplay.getMetrics(metrics)
        val logicalDensity = metrics.density
            override fun onTabUnselected(tab: TabLayout.Tab) {

        itemWidth = Math.ceil(160 * logicalDensity.toDouble()).roundToInt()
        itemPadding = Math.ceil(8 * logicalDensity.toDouble()).roundToInt()
        itemMargin = Math.ceil(4 * logicalDensity.toDouble()).roundToInt()

        itemParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
        itemParams.topMargin = itemPadding
        itemParams.bottomMargin = itemPadding
        itemParams.marginStart = itemPadding
        itemParams.marginEnd = itemPadding
    }

    private fun handleDeviceOrientation() {
        // Check device orientation and increase/decrease number of columns
        val orientation = resources.configuration.orientation
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            // In landscape
            applicationsCategoriesList.columnCount = 3
            gamesCategoriesList.columnCount = 3
        } else {
            // In portrait
            applicationsCategoriesList.columnCount = 2
            gamesCategoriesList.columnCount = 2
        }
            }

    private fun showApplicationsCategories() {
        applicationsCategoriesList.removeAllViews()
        categoriesViewModel.getApplicationsCategories().value!!.forEach {
            val textView = TextView(context)
            textView.layoutParams = itemParams
            textView.width = itemWidth
            textView.setPadding(itemPadding, itemPadding, itemPadding, itemPadding)
            textView.text = it.title
            textView.setTextColor(resources.getColor(android.R.color.black))
            textView.textSize = 16.0f
            textView.gravity = Gravity.CENTER
            textView.maxLines = 1
            textView.ellipsize = TextUtils.TruncateAt.END
            textView.isClickable = true
            if (android.os.Build.VERSION.SDK_INT >= 23) {
                textView.foreground = activity!!.getDrawable(R.drawable.app_category_border)
            }
            val outValue = TypedValue()
            context!!.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
            textView.setBackgroundResource(outValue.resourceId)
            applicationsCategoriesList.addView(textView)
            textView.setOnClickListener { _ ->
                categoriesViewModel.onCategoryClick(context!!, it)
            }
            categoriesContainer.visibility = View.VISIBLE
            progressBar.visibility = View.GONE
        }
    }
            override fun onTabReselected(tab: TabLayout.Tab) {

    private fun showGamesCategories() {
        gamesCategoriesList.removeAllViews()
        categoriesViewModel.getGamesCategories().value!!.forEach {
            val textView = TextView(context)
            textView.layoutParams = itemParams
            textView.width = itemWidth
            textView.setPadding(itemPadding, itemPadding, itemPadding, itemPadding)
            textView.text = it.title
            textView.setTextColor(resources.getColor(android.R.color.black))
            textView.textSize = 16.0f
            textView.gravity = Gravity.CENTER
            textView.maxLines = 1
            textView.ellipsize = TextUtils.TruncateAt.END
            textView.isClickable = true
            if (android.os.Build.VERSION.SDK_INT >= 23) {
                textView.foreground = activity!!.getDrawable(R.drawable.app_category_border)
            }
            val outValue = TypedValue()
            context!!.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
            textView.setBackgroundResource(outValue.resourceId)
            gamesCategoriesList.addView(textView)
            textView.setOnClickListener { _ ->
                categoriesViewModel.onCategoryClick(context!!, it)
            }
            categoriesContainer.visibility = View.VISIBLE
            progressBar.visibility = View.GONE
            }
        })
        return view
    }
}
+46 −0
Original line number Diff line number Diff line
package io.eelo.appinstaller.categories

import android.content.Intent
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.TextView
import io.eelo.appinstaller.R
import io.eelo.appinstaller.categories.category.CategoryActivity
import io.eelo.appinstaller.categories.model.Category
import io.eelo.appinstaller.utils.Common
import io.eelo.appinstaller.utils.Constants

class CategoriesListAdapter(private val categories: ArrayList<Category>)
    : RecyclerView.Adapter<CategoriesListAdapter.CategoryViewHolder>() {

    class CategoryViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val categoryContainer: RelativeLayout = view.findViewById(R.id.category_container)
        val categoryTitle: TextView = view.findViewById(R.id.category_title)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryViewHolder {
        val categoryContainer = LayoutInflater.from(parent.context).inflate(R.layout.category_list_item,
                parent, false)
        return CategoryViewHolder(categoryContainer)
    }

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

    override fun onBindViewHolder(holder: CategoryViewHolder, position: Int) {
        if (categories[position].title.isNullOrEmpty()) {
            categories[position].title = Common.getCategoryTitle(categories[position].id)
        }

        holder.categoryTitle.text = categories[position].title
        holder.categoryContainer.setOnClickListener {
            val intent = Intent(holder.categoryContainer.context, CategoryActivity::class.java)
            intent.putExtra(Constants.CATEGORY_KEY, categories[position])
            holder.categoryContainer.context.startActivity(intent)
        }
    }
}
+27 −0
Original line number Diff line number Diff line
package io.eelo.appinstaller.categories

import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter

class CategoriesViewPagerAdapter(fragmentManager: FragmentManager, private val numberOfTabs: Int) :
        FragmentStatePagerAdapter(fragmentManager) {
    private val applicationsFragment = ApplicationsFragment()
    private val gamesFragment = GamesFragment()

    override fun getItem(position: Int): Fragment? {
        when (position) {
            0 -> {
                return applicationsFragment
            }
            1 -> {
                return gamesFragment
            }
        }
        return null
    }

    override fun getCount(): Int {
        return numberOfTabs
    }
}
Loading