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
+5 -6
View File
@@ -20,15 +20,14 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity android:name=".activities.MainActivity"
android:name=".activities.SettingsActivity" android:configChanges="screenSize|screenLayout|keyboardHidden">
android:label="@string/title_activity_settings" </activity>
android:parentActivityName=".activities.MainActivity"/>
<activity android:name=".activities.AppsListActivity" />
<activity <activity
android:name=".activities.SingleAppActivity" android:name=".activities.SingleAppActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity" /> tools:ignore="LockedOrientationActivity"
android:parentActivityName=".activities.MainActivity" />
</application> </application>
</manifest> </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 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.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem 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.R
import com.illusionware.npsbrowser.databinding.ActivityMainBinding import com.illusionware.npsbrowser.fragments.mainactivity.MainActivityFragment
import kotlinx.android.synthetic.main.appbar.*
import java.io.InputStream
class MainActivity : BaseActivity() { class MainActivity : BaseActivity() {
private val tsvReader = csvReader {
charset = "UTF-8"
quoteChar = '\\'
escapeChar = '\\'
delimiter = '\t'
skipEmptyLine = true
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater) setTheme(R.style.NPSTheme)
setContentView(binding.root) setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
setSupportActionBar(toolbar) supportFragmentManager.beginTransaction()
.replace(R.id.container, MainActivityFragment.newInstance())
binding.tsvChooserButton.setOnClickListener { .commitNow()
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 { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { when (item.itemId) {
R.id.action_settings -> { android.R.id.home -> {
val settingsIntent = Intent(this, SettingsActivity::class.java) supportFragmentManager.popBackStack()
startActivity(settingsIntent) return true
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)
} }
} }
return super.onOptionsItemSelected(item)
} }
private fun isStoragePermissionGranted(): Boolean { fun showUpButton() {
return if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { supportActionBar!!.setDisplayHomeAsUpEnabled(true)
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
}
} }
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.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import com.illusionware.npsbrowser.activities.mainactivity.MainActivity
class SplashActivity : BaseActivity() { class SplashActivity : BaseActivity() {
@@ -12,6 +12,9 @@ import com.illusionware.npsbrowser.R
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context) : RecyclerView.Adapter<AppAdapter.ViewHolder>() { 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) { inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
var appTitle: TextView = view.findViewById(R.id.appTitle) var appTitle: TextView = view.findViewById(R.id.appTitle)
@@ -21,11 +24,29 @@ class AppAdapter(private val appsList: ArrayList<AppData>, val context : Context
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)) 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) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.appTitle.text = appsList[position].title holder.appTitle.text = appsList[position].title
holder.appTitle.isSelected = true
holder.appRegion.text = appsList[position].region holder.appRegion.text = appsList[position].region
holder.appMinFW.text = appsList[position].minFW holder.appMinFW.text = appsList[position].minFW
holder.appMinFW.background = null; holder.appMinFW.background = null;
@@ -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>
+3 -22
View File
@@ -1,26 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout 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" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".activities.MainActivity"> 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>
+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>
+33 -29
View File
@@ -24,23 +24,15 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<TextView <ImageView
android:id="@+id/appRegion" android:id="@+id/imageView"
android:layout_width="40dp" android:layout_width="62dp"
android:layout_height="wrap_content" android:layout_height="56dp"
android:layout_marginStart="24dp" android:contentDescription="app icon"
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_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/appMinFW" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView" /> app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_games_black_24dp" />
<TextView <TextView
android:id="@+id/appTitle" android:id="@+id/appTitle"
@@ -59,17 +51,27 @@
android:textSize="18sp" android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView" 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:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_games_black_24dp" /> 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 <TextView
android:id="@+id/appMinFW" android:id="@+id/appMinFW"
@@ -79,9 +81,10 @@
android:background="@drawable/rect_red" android:background="@drawable/rect_red"
android:padding="4dp" android:padding="4dp"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/colorOnSecondary" android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/appRegion" /> app:layout_constraintStart_toEndOf="@+id/appRegion"
tools:text="3.69" />
<TextView <TextView
android:id="@+id/appLastDate" android:id="@+id/appLastDate"
@@ -90,7 +93,8 @@
android:padding="4dp" android:padding="4dp"
android:textColor="@color/colorOnSecondary" android:textColor="@color/colorOnSecondary"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent"
tools:text="2020-02-12" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView> </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>
+8
View File
@@ -10,4 +10,12 @@
<item>1</item> <item>1</item>
<item>2</item> <item>2</item>
</string-array> </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> </resources>
@@ -8,5 +8,12 @@
android:entryValues="@array/app_theme_val" android:entryValues="@array/app_theme_val"
android:key="app_theme" android:key="app_theme"
android:title="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> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>