use fragments where it makes sense and add grid view with preference option

This commit is contained in:
2020-10-20 17:07:27 +03:00
parent c80ba8ade0
commit 6df9a750b5
18 changed files with 739 additions and 425 deletions
+6 -7
View File
@@ -13,22 +13,21 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/NPSTheme">
<activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash">
<activity android:name=".activities.SplashActivity" android:theme="@style/NPSTheme.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.SettingsActivity"
android:label="@string/title_activity_settings"
android:parentActivityName=".activities.MainActivity"/>
<activity android:name=".activities.AppsListActivity" />
<activity android:name=".activities.MainActivity"
android:configChanges="screenSize|screenLayout|keyboardHidden">
</activity>
<activity
android:name=".activities.SingleAppActivity"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity" />
tools:ignore="LockedOrientationActivity"
android:parentActivityName=".activities.MainActivity" />
</application>
</manifest>
@@ -1,48 +0,0 @@
package com.illusionware.npsbrowser.activities
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.illusionware.npsbrowser.AppData
import com.illusionware.npsbrowser.RecyclerTouchListener
import com.illusionware.npsbrowser.adapters.AppAdapter
import com.illusionware.npsbrowser.databinding.ActivityAppsListBinding
class AppsListActivity : BaseActivity() {
companion object {
lateinit var apps : ArrayList<AppData>
}
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityAppsListBinding.inflate(layoutInflater)
setContentView(binding.root)
viewAdapter = AppAdapter(apps, applicationContext)
recyclerView = binding.appsRecycler
recyclerView.apply {
layoutManager = LinearLayoutManager(applicationContext)
adapter = viewAdapter
recyclerView.addOnItemTouchListener(RecyclerTouchListener(applicationContext, recyclerView, object : RecyclerTouchListener.ClickListener {
override fun onClick(view: View?, position: Int) {
val myIntent = Intent(context, SingleAppActivity::class.java)
SingleAppActivity.app = apps[position]
startActivity(myIntent)
}
override fun onLongClick(view: View?, recyclerView: RecyclerView?, position: Int) {
Toast.makeText(applicationContext, "TODO: Long Click ", Toast.LENGTH_SHORT).show()
}
}
))
}
}
}
@@ -1,108 +1,39 @@
package com.illusionware.npsbrowser.activities
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.core.app.ActivityCompat
import com.github.doyaaaaaken.kotlincsv.dsl.csvReader
import com.illusionware.npsbrowser.AppData
import com.illusionware.npsbrowser.R
import com.illusionware.npsbrowser.databinding.ActivityMainBinding
import kotlinx.android.synthetic.main.appbar.*
import java.io.InputStream
class MainActivity : BaseActivity() {
private val tsvReader = csvReader {
charset = "UTF-8"
quoteChar = '\\'
escapeChar = '\\'
delimiter = '\t'
skipEmptyLine = true
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(toolbar)
binding.tsvChooserButton.setOnClickListener {
if (!isStoragePermissionGranted())
return@setOnClickListener
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/tab-separated-values"
}
startActivityForResult(intent, 1)
}
}
override fun onCreateOptionsMenu(menu : Menu) : Boolean {
menuInflater.inflate(R.menu.toolbar_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
val settingsIntent = Intent(this, SettingsActivity::class.java)
startActivity(settingsIntent)
true
}
else -> return super.onOptionsItemSelected(item)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
val inputStream: InputStream? = contentResolver.openInputStream(uri)
val entries : List<Map<String, String?>> = tsvReader.readAllWithHeader(inputStream!!)
val myIntent = Intent(this, AppsListActivity::class.java)
val apps = ArrayList<AppData>(entries.size)
entries.forEach { entry ->
if (entry["Name"].isNullOrEmpty()) {
return@forEach
}
val id = entry["Title ID"]
val region = entry["Region"]
val name = entry["Name"]
val link = entry["PKG direct link"]
val license = entry["zRIF"]
val contentID = entry["Content ID"]
val lastDateTime = entry["Last Modification Date"]
val fileSize = entry["File Size"]?.toLongOrNull()
val sha256 = entry["SHA256"]
val minFW = entry["Required FW"]
val app = AppData(id, region, name, link ?: "MISSING", license ?: "MISSING",
contentID ?: "MISSING", lastDateTime ?: "MISSING",
fileSize ?: 0, sha256 ?: "MISSING", minFW)
apps.add(app)
}
apps.sortBy { it.title }
AppsListActivity.apps = apps
startActivity(myIntent)
}
}
}
private fun isStoragePermissionGranted(): Boolean {
return if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.v("perms", "Permission is granted")
true
} else {
Log.v("perms", "Permission is revoked")
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
false
}
}
}
package com.illusionware.npsbrowser.activities
import android.os.Bundle
import android.view.MenuItem
import com.illusionware.npsbrowser.R
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.NPSTheme)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, MainActivityFragment.newInstance())
.commitNow()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
supportFragmentManager.popBackStack()
return true
}
}
return super.onOptionsItemSelected(item)
}
fun showUpButton() {
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
}
fun hideUpButton() {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
}
}
@@ -1,35 +0,0 @@
package com.illusionware.npsbrowser.activities
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.illusionware.npsbrowser.R
import com.illusionware.npsbrowser.databinding.SettingsActivityBinding
import kotlinx.android.synthetic.main.appbar.*
class SettingsActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = SettingsActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(toolbar)
supportFragmentManager
.beginTransaction()
.replace(
R.id.settings,
SettingsFragment()
)
.commit()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
}
}
}
@@ -3,7 +3,6 @@ package com.illusionware.npsbrowser.activities
import android.content.Intent
import android.os.Bundle
import android.view.View
import com.illusionware.npsbrowser.activities.mainactivity.MainActivity
class SplashActivity : BaseActivity() {
@@ -1,51 +1,72 @@
package com.illusionware.npsbrowser.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView
import com.illusionware.npsbrowser.AppData
import com.illusionware.npsbrowser.R
import kotlin.collections.ArrayList
class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context) : RecyclerView.Adapter<AppAdapter.ViewHolder>() {
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var appTitle: TextView = view.findViewById(R.id.appTitle)
var appRegion: TextView = view.findViewById(R.id.appRegion)
var appMinFW: TextView = view.findViewById(R.id.appMinFW)
var appLastDate: TextView = view.findViewById(R.id.appLastDate)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.appTitle.text = appsList[position].title
holder.appRegion.text = appsList[position].region
holder.appMinFW.text = appsList[position].minFW
holder.appMinFW.background = null;
if (holder.appMinFW.text.isNotBlank()) {
val drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.rect_red, null)
holder.appMinFW.background = drawable;
}
holder.appLastDate.text = appsList[position].lastDateTime
}
override fun getItemCount(): Int {
return appsList.size
}
fun updateData(apps: ArrayList<AppData>) {
appsList.clear()
notifyDataSetChanged()
appsList.addAll(apps)
notifyDataSetChanged()
}
package com.illusionware.npsbrowser.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView
import com.illusionware.npsbrowser.AppData
import com.illusionware.npsbrowser.R
import kotlin.collections.ArrayList
class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context) : RecyclerView.Adapter<AppAdapter.ViewHolder>() {
private final val LIST_ITEM = 0
private final val GRID_ITEM = 1
var isSwitchView = true
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var appTitle: TextView = view.findViewById(R.id.appTitle)
var appRegion: TextView = view.findViewById(R.id.appRegion)
var appMinFW: TextView = view.findViewById(R.id.appMinFW)
var appLastDate: TextView = view.findViewById(R.id.appLastDate)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return if (viewType == LIST_ITEM) {
ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
} else {
ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.grid_item, parent, false))
}
}
override fun getItemViewType(position: Int): Int {
return if (isSwitchView) {
LIST_ITEM
} else {
GRID_ITEM
}
}
public fun toggleItemViewType(type: Int): Boolean {
isSwitchView = type == 0
return isSwitchView
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.appTitle.text = appsList[position].title
holder.appTitle.isSelected = true
holder.appRegion.text = appsList[position].region
holder.appMinFW.text = appsList[position].minFW
holder.appMinFW.background = null;
if (holder.appMinFW.text.isNotBlank()) {
val drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.rect_red, null)
holder.appMinFW.background = drawable;
}
holder.appLastDate.text = appsList[position].lastDateTime
}
override fun getItemCount(): Int {
return appsList.size
}
fun updateData(apps: ArrayList<AppData>) {
appsList.clear()
notifyDataSetChanged()
appsList.addAll(apps)
notifyDataSetChanged()
}
}
@@ -0,0 +1,65 @@
package com.illusionware.npsbrowser.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.illusionware.npsbrowser.R
import com.illusionware.npsbrowser.activities.BaseActivity
import com.illusionware.npsbrowser.activities.MainActivity
import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
import kotlinx.android.synthetic.main.appbar.*
class SettingsFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (activity!!.supportFragmentManager.backStackEntryCount < 1) {
(activity as MainActivity?)?.showUpButton()
MainActivityFragment().recyclerView?.adapter = MainActivityFragment().viewAdapter
}
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
activity?.supportFragmentManager
?.beginTransaction()
?.replace(
R.id.prefs,
SettingsFragment()
)
?.setTransition(TRANSIT_FRAGMENT_OPEN)
?.commit()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.title = resources.getString(R.string.title_activity_settings)
return inflater.inflate(R.layout.settings_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as BaseActivity?)!!.setSupportActionBar(toolbar)
(activity as BaseActivity?)!!.supportActionBar?.setDisplayHomeAsUpEnabled(true)
//viewModel = ViewModelProviders.of(this).get(MainActivity2ViewModel::class.java)
// TODO: Use the ViewModel
}
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
PreferenceManager.setDefaultValues(context, R.xml.root_preferences, false);
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
//(activity as BaseActivity?)!!.setSupportActionBar(toolbar)
super.onActivityCreated(savedInstanceState)
}
}
}
@@ -0,0 +1,218 @@
package com.illusionware.npsbrowser.fragments.mainactivity
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Toast
import androidx.core.content.ContextCompat.checkSelfPermission
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.ViewModelProviders
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.doyaaaaaken.kotlincsv.dsl.csvReader
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.illusionware.npsbrowser.AppData
import com.illusionware.npsbrowser.R
import com.illusionware.npsbrowser.RecyclerTouchListener
import com.illusionware.npsbrowser.activities.SingleAppActivity
import com.illusionware.npsbrowser.activities.MainActivity
import com.illusionware.npsbrowser.adapters.AppAdapter
import com.illusionware.npsbrowser.fragments.SettingsFragment
import kotlinx.android.synthetic.main.appbar.*
import java.io.InputStream
class MainActivityFragment : Fragment(), FragmentManager.OnBackStackChangedListener {
var recyclerView : RecyclerView? = null
var viewAdapter: AppAdapter? = null
companion object {
fun newInstance() = MainActivityFragment()
var apps : ArrayList<AppData>? = arrayListOf()
}
private val tsvReader = csvReader {
charset = "UTF-8"
quoteChar = '\\'
escapeChar = '\\'
delimiter = '\t'
skipEmptyLine = true
skipMissMatchedRow = true
}
private lateinit var viewModel: MainActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.supportFragmentManager?.addOnBackStackChangedListener(this);
setHasOptionsMenu(true)
}
override fun onBackStackChanged() {
// enable Up button only if there are entries on the backstack
if (requireActivity().supportFragmentManager.backStackEntryCount < 1) {
(activity as MainActivity?)?.hideUpButton()
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
activity?.title = resources.getString(R.string.app_name)
val view = inflater.inflate(R.layout.main_fragment, container, false)
recyclerView = view?.findViewById(R.id.appsRecycler)
if (apps != null) {
viewAdapter = AppAdapter(apps!!, requireContext())
}
viewAdapter?.notifyDataSetChanged()
val orientation = this.resources.configuration.orientation
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val isViewAsList = prefs.getString("layout_type", "0")
if (isViewAsList == "0") {
viewAdapter?.toggleItemViewType(0)
recyclerView?.layoutManager = LinearLayoutManager(context)
viewAdapter?.notifyDataSetChanged()
} else {
viewAdapter?.toggleItemViewType(1)
recyclerView?.layoutManager = GridLayoutManager(context,
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2)
viewAdapter?.notifyDataSetChanged()
}
recyclerView?.adapter = viewAdapter
recyclerView?.addOnItemTouchListener(RecyclerTouchListener(requireContext(), recyclerView!!, object : RecyclerTouchListener.ClickListener {
override fun onClick(view: View?, position: Int) {
val myIntent = Intent(context, SingleAppActivity::class.java)
SingleAppActivity.app = apps!![position]
startActivity(myIntent)
}
override fun onLongClick(view: View?, recyclerView: RecyclerView?, position: Int) {
Toast.makeText(context, "TODO: Long Click ", Toast.LENGTH_SHORT).show()
}
}
))
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as MainActivity?)!!.setSupportActionBar(toolbar)
view?.findViewById<FloatingActionButton>(R.id.tsvChooserButton)?.setOnClickListener {
if (!isStoragePermissionGranted())
return@setOnClickListener
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "text/tab-separated-values"
}
startActivityForResult(intent, 1)
}
viewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
// TODO: Use the ViewModel
}
override fun onCreateOptionsMenu(menu : Menu, menuInflater : MenuInflater) {
menuInflater.inflate(R.menu.toolbar_main, menu)
super.onCreateOptionsMenu(menu, menuInflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_settings -> {
activity?.supportFragmentManager
?.beginTransaction()
?.replace(
R.id.container,
SettingsFragment()
)
?.addToBackStack("settings")
?.commit()
true
}
else -> return super.onOptionsItemSelected(item)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
resultData?.data?.also { uri ->
Log.d("file_location", uri.toString())
val inputStream: InputStream? = activity?.contentResolver?.openInputStream(uri)
val entries : List<Map<String, String?>> = tsvReader.readAllWithHeader(inputStream!!)
apps?.clear()
apps = ArrayList(entries.size)
entries.forEach { entry ->
if (entry["Name"].isNullOrEmpty()) {
return@forEach
}
val id = entry["Title ID"]
val region = entry["Region"]
val name = entry["Name"]
val link = entry["PKG direct link"]
val license = entry["zRIF"]
val contentID = entry["Content ID"]
var lastDateTime = entry["Last Modification Date"]
if (!lastDateTime.isNullOrEmpty()) {
lastDateTime = lastDateTime.substring(0, 10)
}
val fileSize = entry["File Size"]?.toLongOrNull()
val sha256 = entry["SHA256"]
val minFW = entry["Required FW"]
val app = AppData(id, region, name, link ?: "MISSING", license ?: "MISSING",
contentID ?: "MISSING", lastDateTime ?: "MISSING",
fileSize, sha256 ?: "MISSING", minFW)
apps?.add(app)
}
apps?.sortBy { it.title }
recyclerView = view?.findViewById(R.id.appsRecycler)
viewAdapter = AppAdapter(apps!!, requireContext())
val orientation = this.resources.configuration.orientation
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
val isViewAsList = prefs.getString("layout_type", "0")
if (isViewAsList == "0") {
viewAdapter?.toggleItemViewType(0)
recyclerView?.layoutManager = LinearLayoutManager(context)
viewAdapter?.notifyDataSetChanged()
} else {
viewAdapter?.toggleItemViewType(1)
recyclerView?.layoutManager = GridLayoutManager(context,
if (orientation == Configuration.ORIENTATION_LANDSCAPE) 4 else 2)
viewAdapter?.notifyDataSetChanged()
}
recyclerView?.adapter = viewAdapter
}
}
}
private fun isStoragePermissionGranted(): Boolean {
return if (checkSelfPermission(this.context!!, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.v("perms", "Permission is granted")
true
} else {
Log.v("perms", "Permission is revoked")
requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
false
}
}
}
@@ -0,0 +1,7 @@
package com.illusionware.npsbrowser.fragments.mainactivity
import androidx.lifecycle.ViewModel
class MainActivityViewModel : ViewModel() {
// TODO: Implement the ViewModel
}
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appsRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
tools:listitem="@layout/list_item" />
</androidx.constraintlayout.widget.ConstraintLayout>
+7 -26
View File
@@ -1,26 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<include layout="@layout/appbar" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/tsvChooserButton"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_marginStart="176dp"
android:layout_marginEnd="176dp"
android:layout_marginBottom="50dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_add_yellow_24dp"
app:fabCustomSize="52dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:maxImageSize="32dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity" />
+115
View File
@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="0dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="214dp"
app:cardBackgroundColor="@color/colorPrimary"
app:cardElevation="4dp"
app:cardUseCompatPadding="false"
app:contentPadding="15dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_games_black_24dp" />
<TextView
android:id="@+id/appTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:ellipsize="marquee"
android:enabled="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="@color/colorOnPrimary"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView2"
tools:text="App Title" />
<TextView
android:id="@+id/appRegion"
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/rect_light_blue"
android:paddingStart="4dp"
android:paddingLeft="10dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingRight="10dp"
android:paddingBottom="4dp"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="ASIA" />
<TextView
android:id="@+id/appMinFW"
android:layout_width="36dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginBottom="8dp"
android:background="@drawable/rect_red"
android:padding="4dp"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/appRegion"
tools:text="3.69" />
<TextView
android:id="@+id/appLastDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:padding="4dp"
android:textColor="@color/colorOnSecondary"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="2018-04-22" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.cardview.widget.CardView>
+103 -99
View File
@@ -1,100 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="0dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="@color/colorPrimary"
app:cardElevation="4dp"
app:cardUseCompatPadding="false"
app:contentPadding="15dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/appRegion"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:background="@drawable/rect_light_blue"
android:paddingStart="4dp"
android:paddingLeft="10dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingRight="10dp"
android:paddingBottom="4dp"
android:textAlignment="center"
android:textColor="@color/colorOnSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/appMinFW"
app:layout_constraintStart_toEndOf="@+id/imageView" />
<TextView
android:id="@+id/appTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:ellipsize="marquee"
android:focusable="auto"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="@color/colorOnPrimary"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="62dp"
android:layout_height="56dp"
android:contentDescription="game icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_games_black_24dp" />
<TextView
android:id="@+id/appMinFW"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="@drawable/rect_red"
android:padding="4dp"
android:textAlignment="center"
android:textColor="@color/colorOnSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/appRegion" />
<TextView
android:id="@+id/appLastDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:textColor="@color/colorOnSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="0dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="@color/colorPrimary"
app:cardElevation="4dp"
app:cardUseCompatPadding="false"
app:contentPadding="15dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="62dp"
android:layout_height="56dp"
android:contentDescription="app icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_games_black_24dp" />
<TextView
android:id="@+id/appTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:ellipsize="marquee"
android:focusable="auto"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="@color/colorOnPrimary"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent"
tools:text="App Title" />
<TextView
android:id="@+id/appRegion"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:background="@drawable/rect_light_blue"
android:paddingStart="4dp"
android:paddingLeft="10dp"
android:paddingTop="4dp"
android:paddingEnd="4dp"
android:paddingRight="10dp"
android:paddingBottom="4dp"
android:textAlignment="center"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/appMinFW"
app:layout_constraintStart_toEndOf="@+id/imageView"
tools:text="ASIA" />
<TextView
android:id="@+id/appMinFW"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="@drawable/rect_red"
android:padding="4dp"
android:textAlignment="center"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/appRegion"
tools:text="3.69" />
<TextView
android:id="@+id/appLastDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:textColor="@color/colorOnSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="2020-02-12" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</androidx.cardview.widget.CardView>
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
tools:context=".fragments.mainactivity.MainActivityFragment">
<include layout="@layout/appbar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appsRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2"
tools:listitem="@layout/grid_item" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/tsvChooserButton"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_marginBottom="40dp"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_add_yellow_24dp"
app:fabCustomSize="52dp"
app:layout_anchor="@+id/appsRecycler"
app:layout_anchorGravity="bottom|center"
app:maxImageSize="32dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -1,14 +0,0 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="vertical">
<include layout="@layout/appbar" />
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/prefers"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false">
<include
android:id="@+id/include"
layout="@layout/appbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/prefs"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="56dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include">
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+21 -13
View File
@@ -1,13 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="app_theme">
<item>Light</item>
<item>Dark</item>
<item>Use System Default</item>
</string-array>
<string-array name="app_theme_val">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="app_theme">
<item>Light</item>
<item>Dark</item>
<item>Use System Default</item>
</string-array>
<string-array name="app_theme_val">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
<string-array name="layout_type">
<item>List</item>
<item>Grid</item>
</string-array>
<string-array name="layout_type_val">
<item>0</item>
<item>1</item>
</string-array>
</resources>
+18 -11
View File
@@ -1,12 +1,19 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory android:title="Customization">
<com.illusionware.npsbrowser.ThemePreference
android:defaultValue="2"
android:entries="@array/app_theme"
android:entryValues="@array/app_theme_val"
android:key="app_theme"
android:title="Theme" />
</PreferenceCategory>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory android:title="Customization">
<com.illusionware.npsbrowser.ThemePreference
android:defaultValue="2"
android:entries="@array/app_theme"
android:entryValues="@array/app_theme_val"
android:key="app_theme"
android:title="Theme" />
<ListPreference
android:defaultValue="0"
android:entries="@array/layout_type"
android:entryValues="@array/layout_type_val"
android:key="layout_type"
android:title="Layout"
app:useSimpleSummaryProvider="true"/>
</PreferenceCategory>
</PreferenceScreen>