diff --git a/project/app/src/main/AndroidManifest.xml b/project/app/src/main/AndroidManifest.xml index 3317fe57..58294c20 100644 --- a/project/app/src/main/AndroidManifest.xml +++ b/project/app/src/main/AndroidManifest.xml @@ -42,14 +42,14 @@ android:name=".LoginScene.LoginView" android:label="Login" /> diff --git a/project/app/src/main/java/com/nexte/nexte/Entities/User/UserMocker.kt b/project/app/src/main/java/com/nexte/nexte/Entities/User/UserMocker.kt index 140fa8a4..1ac3cbfb 100644 --- a/project/app/src/main/java/com/nexte/nexte/Entities/User/UserMocker.kt +++ b/project/app/src/main/java/com/nexte/nexte/Entities/User/UserMocker.kt @@ -2,6 +2,8 @@ package com.nexte.nexte.Entities.User import java.util.* +@Suppress("DEPRECATION") + object UserMocker { fun generateUsers(): List { diff --git a/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginModel.kt b/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginModel.kt index 10f32fe5..9c0eb4b5 100644 --- a/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginModel.kt +++ b/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginModel.kt @@ -44,7 +44,7 @@ class LoginModel { class AccountKit { companion object { - const val ACCOUNTKIT_CODE = 13 + const val accountKit_code = 13 } /** diff --git a/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginView.kt b/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginView.kt index ab016001..ea71212d 100644 --- a/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginView.kt +++ b/project/app/src/main/java/com/nexte/nexte/LoginScene/LoginView.kt @@ -79,7 +79,7 @@ class LoginView : AppCompatActivity(), LoginDisplayLogic { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { - LoginModel.AccountKit.ACCOUNTKIT_CODE -> { + LoginModel.AccountKit.accountKit_code -> { this.getAccount() } } @@ -138,7 +138,7 @@ class LoginView : AppCompatActivity(), LoginDisplayLogic { val configBuilder = AccountKitConfiguration.AccountKitConfigurationBuilder(LoginType.PHONE, AccountKitActivity.ResponseType.TOKEN) intent.putExtra(AccountKitActivity.ACCOUNT_KIT_ACTIVITY_CONFIGURATION, configBuilder.build()) - startActivityForResult(intent, LoginModel.AccountKit.ACCOUNTKIT_CODE) + startActivityForResult(intent, LoginModel.AccountKit.accountKit_code) } /** @@ -149,7 +149,7 @@ class LoginView : AppCompatActivity(), LoginDisplayLogic { val builder = AccountKitConfiguration.AccountKitConfigurationBuilder(LoginType.EMAIL, AccountKitActivity.ResponseType.TOKEN) intent.putExtra(AccountKitActivity.ACCOUNT_KIT_ACTIVITY_CONFIGURATION, builder.build()) - startActivityForResult(intent, LoginModel.AccountKit.ACCOUNTKIT_CODE) + startActivityForResult(intent, LoginModel.AccountKit.accountKit_code) } /** diff --git a/project/app/src/main/java/com/nexte/nexte/MainActivity.kt b/project/app/src/main/java/com/nexte/nexte/MainActivity.kt index 6c01b138..c24f7546 100644 --- a/project/app/src/main/java/com/nexte/nexte/MainActivity.kt +++ b/project/app/src/main/java/com/nexte/nexte/MainActivity.kt @@ -5,27 +5,30 @@ import android.content.Intent import android.os.Bundle import android.support.v7.app.AppCompatActivity import com.nexte.nexte.LoginScene.* -import com.nexte.nexte.ShowProfileScene.ShowProfileView -import kotlinx.android.synthetic.main.activity_main.* +import com.nexte.nexte.ShowProfileScene.ShowProfileFragment import android.support.design.widget.BottomNavigationView import android.support.v4.app.Fragment -import android.util.Log +import android.widget.Button import com.nexte.nexte.ChallengeScene.ChallengeView import com.nexte.nexte.FeedScene.FeedFragment +import com.nexte.nexte.RankingScene.RankingFragment -import com.nexte.nexte.RankingScene.RankingView +class MainActivity : AppCompatActivity() { + private var bottomNavView: BottomNavigationView?= null + private var loginButton: Button?= null -class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - bottom_nav_view.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) - bottom_nav_view.setOnNavigationItemReselectedListener(mOnNavigationItemReselectedListener) - this.bottom_nav_view.selectedItemId = R.id.profile + bottomNavView =this.findViewById(R.id.bottom_nav_view) + loginButton = this.findViewById(R.id.loginButton) - loginButton.setOnClickListener { + bottomNavView?.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener) + bottomNavView?.setOnNavigationItemReselectedListener(mOnNavigationItemReselectedListener) + bottomNavView?.selectedItemId = R.id.profile + loginButton?.setOnClickListener { val intent = Intent(this, LoginView::class.java) startActivity(intent) } @@ -34,19 +37,17 @@ class MainActivity : AppCompatActivity() { private val mOnNavigationItemReselectedListener = BottomNavigationView.OnNavigationItemReselectedListener { item -> when(item.itemId) { R.id.profile -> { - Log.e("Resultado d", item.itemId.toString()) + /* Do Nothing*/ } } } + private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> - private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item -> - Log.e("Resultado do item", item.itemId.toString()) when (item.itemId) { R.id.feed -> { val feedFragment = FeedFragment().getInstance() openFragment(feedFragment) return@OnNavigationItemSelectedListener true - } R.id.challenge -> { @@ -56,27 +57,27 @@ class MainActivity : AppCompatActivity() { } R.id.ranking -> { - val intent = Intent(this, RankingView::class.java) - startActivity(intent) + val rankingFragment = RankingFragment().getInstance() + openFragment(rankingFragment) return@OnNavigationItemSelectedListener true } R.id.profile -> { - val showProfileFragment = ShowProfileView.newInstance() + val showProfileFragment = ShowProfileFragment().getInstance(UserSingleton.getUserInformations().name) openFragment(showProfileFragment) return@OnNavigationItemSelectedListener true } else -> { - return@OnNavigationItemSelectedListener true - } + return@OnNavigationItemSelectedListener true + } } } private fun openFragment(fragment: Fragment) { - var transaction = supportFragmentManager.beginTransaction() + val transaction = supportFragmentManager.beginTransaction() transaction.replace(R.id.frame_layout,fragment) transaction.addToBackStack(null) transaction.commit() } - } + diff --git a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingView.kt b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingFragment.kt similarity index 72% rename from project/app/src/main/java/com/nexte/nexte/RankingScene/RankingView.kt rename to project/app/src/main/java/com/nexte/nexte/RankingScene/RankingFragment.kt index c60d2619..5b341f04 100644 --- a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingView.kt +++ b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingFragment.kt @@ -1,22 +1,20 @@ package com.nexte.nexte.RankingScene -import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.ColorDrawable -import android.support.v7.app.AppCompatActivity import android.os.Bundle +import android.support.constraint.ConstraintLayout import android.support.constraint.ConstraintSet import android.support.v4.app.Fragment +import android.support.v7.widget.ContentFrameLayout import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.nexte.nexte.R -import com.nexte.nexte.ShowProfileScene.ShowProfileView +import com.nexte.nexte.ShowProfileScene.ShowProfileFragment import com.nexte.nexte.UserSingleton -import kotlinx.android.synthetic.main.activity_ranking.* import kotlinx.android.synthetic.main.row_ranking.view.* import android.support.v7.widget.DividerItemDecoration import com.nexte.nexte.Entities.Challenge.ChallengeManager @@ -33,50 +31,62 @@ interface RankingDisplayLogic { /** * Class that implements [RankingDisplayLogic] - * - * @property interactor responsible to receive request and send it to worker */ -class RankingView : AppCompatActivity(), RankingDisplayLogic { +class RankingFragment : Fragment(), RankingDisplayLogic { - var interactor: RankingInteractor? = null + var interactor: RankingInteractor? = null //interactor responsible to receive request and send it to worker + var rankingRecyclerView: RecyclerView?= null + var fixedFragment: ContentFrameLayout?= null + var rankingConstraintLayout: ConstraintLayout?= null var userManager: UserManager? = null - var challengeManager: ChallengeManager? = null + var challengeManager: ChallengeManager?= null + + fun getInstance() : RankingFragment{ + return RankingFragment() + } /** * Method called on scene creation * * @param savedInstanceState */ + override fun onCreate(savedInstanceState: Bundle?) { userManager = UserManager() challengeManager = ChallengeManager() super.onCreate(savedInstanceState) - setContentView(R.layout.activity_ranking) - - rankingRecyclerView.layoutManager = LinearLayoutManager(this) this.setupRankingScene() + } + + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view: View? = inflater?.inflate(R.layout.activity_ranking, container, false) - val dividerItemDecoration = DividerItemDecoration(this, requestedOrientation) - rankingRecyclerView.addItemDecoration(dividerItemDecoration) + fixedFragment = view?.findViewById(R.id.fixedFragment) + rankingRecyclerView = view?.findViewById(R.id.rankingRecyclerView) + rankingConstraintLayout = view?.findViewById(R.id.rankingConstraintLayout) + rankingRecyclerView?.layoutManager = LinearLayoutManager(this.activity) + val dividerItemDecoration = DividerItemDecoration(this.activity, DividerItemDecoration.VERTICAL) + rankingRecyclerView?.addItemDecoration(dividerItemDecoration) - val fragmentTransaction = supportFragmentManager.beginTransaction() + val fragmentTransaction = fragmentManager.beginTransaction() fragmentTransaction.replace(R.id.fixedFragment, FixedRowRankingFragment()) fragmentTransaction.commit() this.createGetPlayersRequest() - this.rankingRecyclerView.addOnScrollListener(OnScrollRankingRecyclerView( + this.rankingRecyclerView?.addOnScrollListener(OnScrollRankingRecyclerView( UserSingleton.getUserInformations().rankingPosition, this)) setFixedRanking(this, this.rankingRecyclerView, UserSingleton.getUserInformations().rankingPosition) - } + return view + } - private fun goToShowProfileView() { - val intent = Intent(this, ShowProfileView::class.java) - startActivity(intent) + private fun goToShowProfileView(name: String?) { + val fragment = ShowProfileFragment().getInstance(name) + fragmentManager.beginTransaction().replace(R.id.frame_layout, fragment).addToBackStack(null).commit() } @@ -103,25 +113,25 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { /** * Function responsible to define when or where the fixed ranking row should appear * - * @param context indicates the context that the fragment is contained in + * @param fragment indicates the fragment that this fragment is contained in * @param recyclerView indicates the recycler view that will be used to control how the fixed row will be displayed * @param playerRanking Indicates the player position that will be shown on screen, and it is used for comparision. */ - private fun setFixedRanking(context: Context, recyclerView: RecyclerView?, playerRanking: Int) { + private fun setFixedRanking(fragment: Fragment, recyclerView: RecyclerView?, playerRanking: Int) { val constraintSet = ConstraintSet() - val rankingView = context as RankingView + val rankingView = fragment as RankingFragment val layoutManager = recyclerView?.layoutManager as LinearLayoutManager if(layoutManager.findFirstCompletelyVisibleItemPosition() <= playerRanking - 1 && playerRanking - 1 <= layoutManager.findLastCompletelyVisibleItemPosition()) { - rankingView.fixedFragment.visibility = View.INVISIBLE + rankingView.fixedFragment?.visibility = View.INVISIBLE } else if (playerRanking - 1 > layoutManager.findLastCompletelyVisibleItemPosition()) { - rankingView.fixedFragment.visibility = View.VISIBLE + rankingView.fixedFragment?.visibility = View.VISIBLE constraintSet.clone(rankingView.rankingConstraintLayout) constraintSet.clear(R.id.fixedFragment, ConstraintSet.BOTTOM) constraintSet.clear(R.id.fixedFragment, ConstraintSet.TOP) @@ -131,7 +141,7 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { else if (playerRanking - 1 < layoutManager.findFirstCompletelyVisibleItemPosition()){ - rankingView.fixedFragment.visibility = View.VISIBLE + rankingView.fixedFragment?.visibility = View.VISIBLE constraintSet.clone(rankingView.rankingConstraintLayout) constraintSet.clear(R.id.fixedFragment, ConstraintSet.BOTTOM) constraintSet.clear(R.id.fixedFragment, ConstraintSet.TOP) @@ -144,13 +154,13 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { * Class responsible to control recycler view scrolling * * @param playerRanking indicates the position of the logged user - * @param context indicates the context that the recycler view is inserted in + * @param fragment indicates the fragment that the recycler view is inserted in */ - private class OnScrollRankingRecyclerView(val playerRanking: Int, val context: Context) : RecyclerView.OnScrollListener() { + private class OnScrollRankingRecyclerView(val playerRanking: Int, val fragment: Fragment) : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { - (context as RankingView).setFixedRanking(context, recyclerView, playerRanking) + (fragment as RankingFragment).setFixedRanking(fragment, recyclerView, playerRanking) } } @@ -186,17 +196,17 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { */ override fun displayRankingInScreen(viewModel: RankingModel.ViewModel) { - rankingRecyclerView.adapter = RankingAdapter(viewModel.formattedPlayers, this) + rankingRecyclerView?.adapter = RankingAdapter(viewModel.formattedPlayers, this) } /** * Class responsible to expand user information on click * * @property playerInformation List of formatted information - * @property context Context that will show this adapter + * @property fragment Fragment that will show this adapter */ class RankingAdapter(private val playerInformation: List, - private val context: Context): RecyclerView.Adapter() { + private val fragment: Fragment): RecyclerView.Adapter() { private var expandedId = -1 @@ -209,7 +219,7 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { */ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val inflater = LayoutInflater.from(context) + val inflater = LayoutInflater.from(fragment.activity) val view: View? view = inflater.inflate(R.layout.row_ranking, parent, false) @@ -254,7 +264,7 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { itemHolder?.lastGame?.text = item.player.userLastGame itemHolder?.efficiency?.text = item.player.userEfficiency itemHolder?.profileButton?.setOnClickListener{ - (context as RankingView).goToShowProfileView() + (fragment as RankingFragment).goToShowProfileView(item.player.userName) } if(expandedId == itemHolder?.layoutPosition) { @@ -278,14 +288,14 @@ class RankingView : AppCompatActivity(), RankingDisplayLogic { */ inner class ItemHolder(v: View): RecyclerView.ViewHolder(v) { - var nameText = v.name - var rankingText = v.position - var victory = v.victory - var lastGame = v.lastGame - var expandedView = v.expandedView - var efficiency = v.efficiency - var profileButton = v.profileButton - var playerCategory = v.playerCategory + var nameText = v.name!! + var rankingText = v.position!! + var victory = v.victory!! + var lastGame = v.lastGame!! + var expandedView = v.expandedView!! + var efficiency = v.efficiency!! + var profileButton = v.profileButton!! + var playerCategory = v.playerCategory!! } } } \ No newline at end of file diff --git a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingModel.kt b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingModel.kt index 1275fda8..d90e06cd 100644 --- a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingModel.kt +++ b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingModel.kt @@ -33,26 +33,6 @@ class RankingModel { //-------------- Aux Classes -------------- - /** - * Class responsible to define personal data of all players - * - * @property name it's the name of the player - * @property pictureURL it's the photo of the player - * @property playerCategory it's the category that the player plays - * @property wins are all the games won by the player - * @property losses are all the games lost by the player - * @property rankingPosition it's the position of the player on the ranking - * @property lastGame it's when the user player the last - */ - class Player(var name: String, - var pictureURL: Int, - var playerCategory: String, - var wins: Int, - var losses: Int, - var rankingPosition: Int, - var lastGame: String, - var efficiency: String) - /** * Class responsible to define format players information * diff --git a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingPresenter.kt b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingPresenter.kt index e1f37148..458e8f2b 100644 --- a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingPresenter.kt +++ b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingPresenter.kt @@ -1,9 +1,9 @@ package com.nexte.nexte.RankingScene -import com.nexte.nexte.Entities.Challenge.Challenge -import com.nexte.nexte.Entities.Challenge.ChallengeManager import com.nexte.nexte.Entities.User.User import com.nexte.nexte.R +import com.nexte.nexte.Entities.Challenge.Challenge +import com.nexte.nexte.Entities.Challenge.ChallengeManager import java.util.* /** @@ -23,7 +23,7 @@ interface RankingPresentationLogic { /** * Class needed to format response for data can be displayed on View * - * @property viewScene Reference to the ranking where data will be displayed on [RankingView] + * @property viewScene Reference to the ranking where data will be displayed on [RankingFragment] */ class RankingPresenter( var viewScene: RankingDisplayLogic? = null) : RankingPresentationLogic { @@ -31,7 +31,7 @@ class RankingPresenter( var viewScene: RankingDisplayLogic? = null) : RankingPre /** * Formats user information contained in [RankingModel.Response] - * and sends it to [RankingView] + * and sends it to [RankingFragment] * * @param response contains unformatted data received from [RankingModel] */ @@ -61,7 +61,7 @@ class RankingPresenter( var viewScene: RankingDisplayLogic? = null) : RankingPre val lastGame = calculatePlayerLastGame(user.latestGames) var playerCategory = "" if (user.category != null){ - playerCategory = user.category?.name + playerCategory = user.category.name } val playerFormatted = RankingModel.FormattedPlayer(name, R.mipmap.ic_launcher, String.format("Vitórias: %d", wins), @@ -89,7 +89,7 @@ class RankingPresenter( var viewScene: RankingDisplayLogic? = null) : RankingPre efficiency = "0%" } - return efficiency!! + return efficiency } /** @@ -104,25 +104,20 @@ class RankingPresenter( var viewScene: RankingDisplayLogic? = null) : RankingPre val latestGameDate = latestGames.first().challengeDate val today = Date() - var latestGame = "Nenhum jogo" - if(today.year == latestGameDate.year){ + return if(today.year == latestGameDate.year){ if (today.month == latestGameDate.month){ - if (today.day == latestGameDate.day){ - latestGame = "hoje" - }else if(today.day == latestGameDate.day - 1){ - latestGame = "ontem" - }else{ - latestGame = "" + (today.day - latestGameDate.day) + " days" + when { + today.day == latestGameDate.day -> "hoje" + today.day == latestGameDate.day - 1 -> "ontem" + else -> "" + (today.day - latestGameDate.day) + " days" } }else{ - latestGame = "" + (today.month - latestGameDate.month) + " months" + "" + (today.month - latestGameDate.month) + " months" } }else{ - latestGame = "" + (today.year - latestGameDate.year) + " years" + "" + (today.year - latestGameDate.year) + " years" } - - return latestGame } companion object { diff --git a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingWorker.kt b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingWorker.kt index 2ff89115..5b2a1ada 100644 --- a/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingWorker.kt +++ b/project/app/src/main/java/com/nexte/nexte/RankingScene/RankingWorker.kt @@ -35,16 +35,15 @@ class RankingWorker { * Function to get users in ranking * * @param request Ranking Model Request that contains need information to send for server - * @param completion Method to call on parent class */ fun getUsersInRanking(request: RankingModel.Request) { - val users = userManager?.getAll() + val users = userManager?.getAll()?.sortedBy { it.rankingPosition } val response = RankingModel.Response(users!!.toTypedArray()) updateLogic?.updateUsersInRanking(response) val url = "http://10.0.2.2:3000/users" - url.httpGet().responseJson { request, response, result -> + url.httpGet().responseJson { _, _, result -> when(result){ is Result.Failure -> { println(result.getException()) @@ -52,15 +51,13 @@ class RankingWorker { is Result.Success -> { val json = result.get() - var usersList = convertJsonToListOfUsers(json.obj()) + var usersList = convertJsonToListOfUsers(json.obj()).sortedBy { it.rankingPosition } usersList = userManager?.updateMany(usersList)!! val newResponse = RankingModel.Response(usersList.toTypedArray()) - updateLogic?.updateUsersInRanking(newResponse) } } } - } /** @@ -71,12 +68,12 @@ class RankingWorker { * * @return list of users */ - private fun convertJsonToListOfUsers(jsonObject: JSONObject): List{ + fun convertJsonToListOfUsers(jsonObject: JSONObject): List{ val dataJson = jsonObject["data"] as JSONObject val usersJsonArray = dataJson["users"] as JSONArray - var usersMutableList = mutableListOf() - for (counter in 0..usersJsonArray.length()-1){ + val usersMutableList = mutableListOf() + for (counter in 0 until usersJsonArray.length()){ val jsonUser = usersJsonArray.getJSONObject(counter) val user = User.createUserFromJsonObject(jsonUser) usersMutableList.add(user) diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileFragment.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileFragment.kt new file mode 100644 index 00000000..b7c45df8 --- /dev/null +++ b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileFragment.kt @@ -0,0 +1,280 @@ +package com.nexte.nexte.ShowProfileScene + +import android.content.Intent +import android.support.v4.app.Fragment +import android.graphics.Color +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.IndexAxisValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.nexte.nexte.EditProfileScene.EditProfileView +import com.nexte.nexte.Entities.User.UserManager +import com.nexte.nexte.R +import com.nexte.nexte.UserSingleton +import kotlinx.android.synthetic.main.activity_show_profile.* + +/** + * This interface will be responsible to define the methods that + * will receive the formatted data from [ShowProfilePresenter] + */ +interface ShowProfileDisplayLogic { + + fun displayProfile(viewModel : ShowProfileModel.ViewModel) +} + +@Suppress("DEPRECATION") + +/** + * This class implements ShowProfileDisplayLogic, and it is responsible to + * display information about the user + * + * @property showProfileInteractor responsible to receive request and send it to worker + */ +class ShowProfileFragment : Fragment(), ShowProfileDisplayLogic { + + var showProfileInteractor: ShowProfileBusinessLogic? = null + var buttonEditProfile: Button? = null + var rankingChart: LineChart? = null + private var newLineChart: LineChart? = null + private var anotherPlayerName: String = "" + var userManager: UserManager? = null + val graphManager = GraphManager(this) + + /* + This method is called on instantiate, and it's responsible to set the player that the profile will be + displayed + */ + fun getInstance(playerToShowName: String?): ShowProfileFragment { + + val bundle = Bundle() + val showProfileFragment = ShowProfileFragment() + + if (playerToShowName != null) { + bundle.putString("anotherPlayerName", playerToShowName) + } else { + bundle.putString("anotherPlayerName", "") + } + + showProfileFragment.arguments = bundle + return showProfileFragment + } + + + /** + * Method called when screen is loaded, responsible to load user information + */ + override fun onCreate(savedInstanceState: Bundle?) { + + super.onCreate(savedInstanceState) + this.userManager = UserManager() + setupShowProfileScene() + this.anotherPlayerName = arguments.getString("anotherPlayerName") + } + + + override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { + + val newView = inflater?.inflate(R.layout.activity_show_profile, container, false) + buttonEditProfile = newView?.findViewById(R.id.editProfileButton) + + buttonEditProfile?.setOnClickListener { + val intent = Intent(activity, EditProfileView::class.java) + startActivity(intent) + } + + this.createShowProfileRequest() + + newLineChart = newView?.findViewById(R.id.lineChart) + rankingChart = newView?.findViewById(R.id.rankingChart) + + this.graphManager.createGraph() + this.graphManager.createRankingGraph() + + + return newView + } + + /** + * Method responsible for creating the show profile request and passing it to the interactor + */ + fun createShowProfileRequest() { + val showUserProfileRequest: ShowProfileModel.Request = ShowProfileModel.Request(anotherPlayerName) + this.showProfileInteractor?.showProfile(showUserProfileRequest) + + } + + /** + * class used to manage graph data and exhibition + */ + class GraphManager (var showProfileFragment : ShowProfileFragment) { + /** + * Method responsible to define the data of Y axis. + */ + + fun setYAxisValues(): ArrayList { + + val yVals = ArrayList() + + yVals.add(Entry(0f, 2f)) + yVals.add(Entry(1f, 3f)) + yVals.add(Entry(2f, 4f)) + yVals.add(Entry(3f, 2f)) + yVals.add(Entry(4f, 1f)) + yVals.add(Entry(5f, 5f)) + + + return yVals + } + + /** + * Method responsible to define the data of Y axis. + */ + + fun setYAxisValuesRanking(): ArrayList { + + val yValsRanking = ArrayList() //array responsible to store all values of Y + + yValsRanking.add(Entry(0f, 3f)) + yValsRanking.add(Entry(1f, 2f)) + yValsRanking.add(Entry(2f, 5f)) + yValsRanking.add(Entry(3f, 2f)) + yValsRanking.add(Entry(4f, 1f)) + yValsRanking.add(Entry(5f, 4f)) + + return yValsRanking + } + + /** + * Method responsible to create the graph, using the function and + * SetYAxisValues. + */ + + fun createGraph() { + + val xAxis = showProfileFragment.newLineChart?.xAxis //instance a view from xml. + val yAxes = setYAxisValues() //responsible to access the method setYAxisValues + val dataSets = ArrayList() // Created an array which has type ILineDataSet(Type defined by MPAndroidChart) + + val line = LineDataSet(yAxes, "Vitoria") /*Access the data of yAxes, introduce a + legend and customize the graphic*/ + line.fillAlpha = houndredLine + line.color = Color.BLUE + line.axisDependency = YAxis.AxisDependency.LEFT + dataSets.add(line) + + //Responsible to create an array that store the string about last months of matches of the user + val lastMonths = arrayOf("Set", "Out", "Nov", "Dez", "Jan", "Fev") + xAxis?.valueFormatter = IndexAxisValueFormatter(lastMonths) + xAxis?.granularity = 1f + xAxis?.textColor = Color.WHITE + + //LineData, access the data defined, and xml LineChart have access to it + val points = LineData(dataSets) + points.setValueTextColor(Color.WHITE) + + val lineData = LineData(dataSets) + showProfileFragment.newLineChart?.data = lineData + showProfileFragment.newLineChart?.axisLeft?.setAxisMaxValue(8f) + showProfileFragment.newLineChart?.axisLeft?.setAxisMinValue(0f) + showProfileFragment.newLineChart?.axisRight?.setAxisMaxValue(0f) + showProfileFragment.newLineChart?.axisRight?.setAxisMinValue(8f) + showProfileFragment.newLineChart?.axisLeft?.setDrawGridLines(false) + showProfileFragment.newLineChart?.xAxis?.setDrawGridLines(false) + showProfileFragment.newLineChart?.setScaleEnabled(false) + showProfileFragment.newLineChart?.invalidate() + } + + /** + * Method responsible to create the graph, using the function + * SetYAxisValuesRanking. + */ + + fun createRankingGraph() { + + val xAxisRanking = showProfileFragment.rankingChart?.xAxis //instance a view from xml. + val yAxesRanking = setYAxisValuesRanking() //responsible to access the method setYAxisValuesRanking + val dataSetsRanking = ArrayList()//Created an array which has type ILineDataSet(Type defined by MPAndroidChart) + + Log.e("Entrou", "aqui") + + val lineRanking = LineDataSet(yAxesRanking, "Posição no Ranking") //Access the data of yAxes, + // introduce a legend and customize the graphic + lineRanking.fillAlpha = houndredLine + lineRanking.color = Color.RED + lineRanking.axisDependency = YAxis.AxisDependency.LEFT + dataSetsRanking.add(lineRanking) + + val lastMonths = arrayOf("Set", "Out", "Nov", "Dez", "Jan", "Fev") //Responsible to create an array that store the + // string about last months of matches of the user + xAxisRanking?.valueFormatter = IndexAxisValueFormatter(lastMonths) + xAxisRanking?.granularity = 1f + xAxisRanking?.textColor = Color.WHITE + + val points = LineData(dataSetsRanking) //access the data defined, and xml LineChart have access to it + points.setValueTextColor(Color.WHITE) + + val rankingData = LineData(dataSetsRanking) + showProfileFragment.rankingChart?.data = rankingData + showProfileFragment.rankingChart?.axisLeft?.setAxisMaxValue(8f) + showProfileFragment.rankingChart?.axisLeft?.setAxisMinValue(0f) + showProfileFragment.rankingChart?.axisRight?.setAxisMaxValue(0f) + showProfileFragment.rankingChart?.axisRight?.setAxisMinValue(8f) + showProfileFragment.rankingChart?.axisLeft?.setDrawGridLines(false) + showProfileFragment.rankingChart?.xAxis?.setDrawGridLines(false) + showProfileFragment.rankingChart?.setScaleEnabled(false) + showProfileFragment.rankingChart?.invalidate() + } + } + + /** + * This method is called when user edits information. + */ + override fun onResume() { + super.onResume() + this.createShowProfileRequest() + } + + /** + * Method responsible to set all the references on this scene + */ + fun setupShowProfileScene() { + + val viewScene = this + val interactor = ShowProfileInteractor() + val presenter = ShowProfilePresenter() + + interactor.presenter = presenter + presenter.viewScene = viewScene + viewScene.showProfileInteractor = interactor + interactor.worker.userManager = userManager + } + + /** + * Method responsible to receive data from presenter and show it + * + * @param viewModel Contains the formatted data to be displayed + */ + override fun displayProfile(viewModel: ShowProfileModel.ViewModel) { + + username?.text = viewModel.playerInfo.name + RankingID?.text = viewModel.playerInfo.rank + email?.text = viewModel.playerInfo.email + if(viewModel.playerInfo.name != UserSingleton.getUserInformations().name){ + buttonEditProfile?.visibility = View.INVISIBLE + } + } + + companion object { + const val houndredLine = 110 + } +} + diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileInteractor.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileInteractor.kt index 95e7c59b..c27c7fef 100644 --- a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileInteractor.kt +++ b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileInteractor.kt @@ -28,7 +28,7 @@ interface ShowProfileBusinessLogic { */ class ShowProfileInteractor : ShowProfileBusinessLogic { - private var worker = ShowProfileWorker() + var worker = ShowProfileWorker() var presenter : ShowProfilePresentationLogic? = null /** diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileModel.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileModel.kt index 6895c4f5..7ae4645c 100644 --- a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileModel.kt +++ b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileModel.kt @@ -1,5 +1,6 @@ package com.nexte.nexte.ShowProfileScene +import com.nexte.nexte.Entities.User.User import com.nexte.nexte.Player /** @@ -16,14 +17,14 @@ class ShowProfileModel { * @property username variable that holds the name chosen by the user on the app * @property tokenID variable that holds the token that validates the user in the system **/ - class Request(var username: String, var tokenID: String) + class Request(var username: String) /** * Class responsible to store received information of worker to pass for Presenter * * @property user variable that return the attributes of player after the validation step **/ - class Response(var user: Player?) + class Response(var user: User?) /** * Class responsible to define how the list view will display the formatted data, passed to view @@ -46,7 +47,5 @@ class ShowProfileModel { class FormattedPlayer( var name: String?, var rank: String?, - var club: String?, - var email: String?, - var age: String?) + var email: String?) } diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfilePresenter.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfilePresenter.kt index a95d9a5b..908257c8 100644 --- a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfilePresenter.kt +++ b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfilePresenter.kt @@ -17,7 +17,7 @@ interface ShowProfilePresentationLogic { /** * This class will be responsible to receive a [ShowProfileModel.Response] - * and generate a [ShowProfileModel.ViewModel], sending it to the [ShowProfileView] + * and generate a [ShowProfileModel.ViewModel], sending it to the [ShowProfileFragment] * * @property viewScene Reference to display formatted data */ @@ -27,7 +27,7 @@ class ShowProfilePresenter : ShowProfilePresentationLogic { /** * This method is responsible for formatting data contained on - * [ShowProfileModel.Response] and send it to [ShowProfileView] + * [ShowProfileModel.Response] and send it to [ShowProfileFragment] * * @param response contains unformatted data received from [ShowProfileModel] */ @@ -35,16 +35,11 @@ class ShowProfilePresenter : ShowProfilePresentationLogic { val name: String? = response.user?.name val ranking: String? = "#" + response.user?.rankingPosition.toString() - val club: String? = response.user?.club val email: String? = response.user?.email - val age: String? = response.user?.age.toString() - val formattedPlayer : ShowProfileModel.FormattedPlayer = ShowProfileModel.FormattedPlayer( name, ranking, - club, - email, - age) + email) val viewModel : ShowProfileModel.ViewModel = ShowProfileModel.ViewModel(formattedPlayer) diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileView.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileView.kt deleted file mode 100644 index c2bbf1e0..00000000 --- a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileView.kt +++ /dev/null @@ -1,277 +0,0 @@ -package com.nexte.nexte.ShowProfileScene - -import android.content.Intent -import android.support.v4.app.Fragment -import android.graphics.Color -import android.os.Bundle -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Button -import com.github.mikephil.charting.charts.LineChart -import com.github.mikephil.charting.components.YAxis -import com.github.mikephil.charting.data.Entry -import com.github.mikephil.charting.data.LineData -import com.github.mikephil.charting.data.LineDataSet -import com.github.mikephil.charting.formatter.IndexAxisValueFormatter -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet -import com.nexte.nexte.EditProfileScene.EditProfileView -import com.nexte.nexte.R -import kotlinx.android.synthetic.main.activity_show_profile.* - -/** - * This interface will be responsible to define the methods that - * will receive the formatted data from [ShowProfilePresenter] - */ -interface ShowProfileDisplayLogic { - - fun displayProfile(viewModel : ShowProfileModel.ViewModel) -} - -@Suppress("DEPRECATION") - -/** - * This class implements ShowProfileDisplayLogic, and it is responsible to - * display information about the user - * - * @property showProfileInteractor responsible to receive request and send it to worker - */ -class ShowProfileView : Fragment(), ShowProfileDisplayLogic { - - var showProfileInteractor : ShowProfileBusinessLogic? = null - var buttonEditProfile : Button? = null - var rankingChart : LineChart? = null - var newLineChart : LineChart? = null - - /** - * Method called when screen is loaded, responsible to load user information - */ - override fun onCreate(savedInstanceState: Bundle?) { - - super.onCreate(savedInstanceState) - setupShowProfileScene() - - this.createShowProfileRequest() - - } - - - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { - - val newView = inflater?.inflate(R.layout.activity_show_profile, container, false) - buttonEditProfile = newView?.findViewById(R.id.editProfileButton) - buttonEditProfile?.setOnClickListener { - val intent = Intent(activity, EditProfileView::class.java) - startActivity(intent) - } - - - newLineChart = newView?.findViewById(R.id.lineChart) - rankingChart = newView?.findViewById(R.id.rankingChart) - - this.createGraph() - this.createRankingGraph() - - - return newView - - - } - /** - * Method responsible for creating the show profile request and passing it to the interactor - */ - fun createShowProfileRequest() { - val showUserProfileRequest: ShowProfileModel.Request = ShowProfileModel.Request("gabrielalbino", - "AUFDSASFSA321IEUNFDI23FIQ2F") - this.showProfileInteractor?.showProfile(showUserProfileRequest) - - } - - - /** - * Method responsable to define a param to X axis. - * @property xVals array responsable to store all values of X - * @property tam responsable to store the data of X axis. - */ - - fun setXAxisValues(): ArrayList { - - val xVals = ArrayList() - - return xVals - } - - /** - * Method responsible to define the data of Y axis. - * @property yVals array responsible to store all values of Y - */ - - fun setYAxisValues(): ArrayList { - - val yVals = ArrayList() - - yVals.add(Entry(0f, 2f)) - yVals.add(Entry(1f, 3f)) - yVals.add(Entry(2f, 4f)) - yVals.add(Entry(3f, 2f)) - yVals.add(Entry(4f, 1f)) - yVals.add(Entry(5f, 5f)) - - - return yVals - } - - /** - * Method responsible to define the data of Y axis. - * @property yValsRanking array responsible to store all values of Y - */ - - fun setYAxisValuesRanking(): ArrayList { - - val yValsRanking = ArrayList() - - yValsRanking.add(Entry(0f, 3f)) - yValsRanking.add(Entry(1f, 2f)) - yValsRanking.add(Entry(2f, 5f)) - yValsRanking.add(Entry(3f, 2f)) - yValsRanking.add(Entry(4f, 1f)) - yValsRanking.add(Entry(5f, 4f)) - - return yValsRanking - } - - /** - * Method responsible to create the graph, using the function and - * SetYAxisValues. - * @property lineChart instance a view from xml. - * @property yAxes responsible to access the method setYAxisValues - * @property dataSet Created an array which has type ILineDataSet(Type defined by MPAndroidChart) - * @property line Access the data of yAxes, introduce a legend and customize the graphic - * @property lastMonths Responsible to create an array that store the string about last months of matches of the user - * @property lineData Type: LineData, access the data defined, and xml LineChart have access to it - */ - - fun createGraph() { - - val xAxis = newLineChart?.xAxis - val xAxes = setXAxisValues() - val yAxes = setYAxisValues() - val dataSets = ArrayList() - - val line = LineDataSet(yAxes, "Vitoria") - line.fillAlpha = houndredLine - line.color = Color.BLUE - line.axisDependency =YAxis.AxisDependency.LEFT - dataSets.add(line) - - val lastMonths = arrayOf("Set", "Out", "Nov", "Dez","Jan","Fev") - xAxis?.valueFormatter = IndexAxisValueFormatter(lastMonths) - xAxis?.granularity = 1f - xAxis?.textColor = Color.WHITE - - val points = LineData(dataSets) - points.setValueTextColor(Color.WHITE) - - val lineData = LineData(dataSets) - newLineChart?.data = lineData - newLineChart?.axisLeft?.setAxisMaxValue(8f) - newLineChart?.axisLeft?.setAxisMinValue(0f) - newLineChart?.axisRight?.setAxisMaxValue(0f) - newLineChart?.axisRight?.setAxisMinValue(8f) - newLineChart?.axisLeft?.setDrawGridLines(false) - newLineChart?.xAxis?.setDrawGridLines(false) - newLineChart?.setScaleEnabled(false) - newLineChart?.invalidate() - } - /** - * Method responsible to create the graph, using the function - * SetYAxisValuesRanking. - * @property rankingChart instance a view from xml. - * @property yAxesRanking responsible to access the method setYAxisValuesRanking - * @property dataSetsRanking Created an array which has type ILineDataSet(Type defined by MPAndroidChart) - * @property lineRanking Access the data of yAxes, introduce a legend and customize the graphic - * @property lastMonths Responsible to create an array that store the string about last months of matches of the user - * @property RankingData Type: LineData, access the data defined, and xml LineChart have access to it - */ - - fun createRankingGraph() { - - val xAxisRanking = rankingChart?.xAxis - val yAxesRanking = setYAxisValuesRanking() - val dataSetsRanking = ArrayList() - - Log.e("Entrou", "aqui") - - val lineRanking = LineDataSet(yAxesRanking, "Posição no Ranking") - lineRanking.fillAlpha = houndredLine - lineRanking.color = Color.RED - lineRanking.axisDependency =YAxis.AxisDependency.LEFT - dataSetsRanking.add(lineRanking) - - val lastMonths = arrayOf("Set", "Out", "Nov", "Dez","Jan","Fev") - xAxisRanking?.valueFormatter = IndexAxisValueFormatter(lastMonths) - xAxisRanking?.granularity = 1f - xAxisRanking?.textColor = Color.WHITE - - val points = LineData(dataSetsRanking) - points.setValueTextColor(Color.WHITE) - - val rankingData = LineData(dataSetsRanking) - rankingChart?.data = rankingData - rankingChart?.axisLeft?.setAxisMaxValue(8f) - rankingChart?.axisLeft?.setAxisMinValue(0f) - rankingChart?.axisRight?.setAxisMaxValue(0f) - rankingChart?.axisRight?.setAxisMinValue(8f) - rankingChart?.axisLeft?.setDrawGridLines(false) - rankingChart?.xAxis?.setDrawGridLines(false) - rankingChart?.setScaleEnabled(false) - rankingChart?.invalidate() - } - - /** - * This method is called when user edits information. - */ - override fun onResume() { - - super.onResume() - - this.createShowProfileRequest() - } - - /** - * Method responsible to set all the references on this scene - */ - fun setupShowProfileScene() { - - val viewScene = this - val interactor = ShowProfileInteractor() - val presenter = ShowProfilePresenter() - - interactor.presenter = presenter - presenter.viewScene = viewScene - viewScene.showProfileInteractor = interactor - } - - /** - * Method responsible to receive data from presenter and show it - * - * @param viewModel Contains the formatted data to be displayed - */ - override fun displayProfile(viewModel: ShowProfileModel.ViewModel) { - - username?.text = viewModel.playerInfo.name - RankingID?.text = viewModel.playerInfo.rank - club?.text = viewModel.playerInfo.club - age?.text = viewModel.playerInfo.age - email?.text = viewModel.playerInfo.email - } - - companion object { - const val houndredLine = 110 - - fun newInstance(): ShowProfileView = ShowProfileView() - - } - } - diff --git a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileWorker.kt b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileWorker.kt index ec5f127c..a5b3c724 100644 --- a/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileWorker.kt +++ b/project/app/src/main/java/com/nexte/nexte/ShowProfileScene/ShowProfileWorker.kt @@ -1,8 +1,8 @@ package com.nexte.nexte.ShowProfileScene -import com.nexte.nexte.UserSingleton -import com.nexte.nexte.Player - +import com.nexte.nexte.Entities.User.User +import com.nexte.nexte.Entities.User.UserCategory.UserCategory +import com.nexte.nexte.Entities.User.UserManager /** * This class verifies if the logged user is valid and return the user information as response. * She format Response and call completion to send data for called class @@ -10,6 +10,7 @@ import com.nexte.nexte.Player class ShowProfileWorker { + var userManager: UserManager? = null /** * Method responsible to get the [ShowProfileModel.Request] with data to be validated * and generate an [ShowProfileModel.Response] with user information @@ -21,26 +22,25 @@ class ShowProfileWorker { completion: (ShowProfileModel.Response) -> Unit) { val username = request.username - val tokenID = request.tokenID + val userList = userManager?.getAll()?.sortedBy { it.rankingPosition } - val emptyUser = Player("", - -1, - "", - "", - "", - "", - -1, - "", - "") + val emptyUser = User("", "", "", "", null, -1, + "", "", -1, -1, User.Gender.FEMALE, UserCategory("", ""), + User.Status.UNAVAILABLE,null, null, null) - var returnedUser: Player? = null + var returnedUser: User? = null // This condition verifies if exists a user - if(tokenID.equals("")) { + if(userList != null){ + for(user in userList){ + if(user.name == username){ + returnedUser = user + break + } + } + } + if(returnedUser == null){ returnedUser = emptyUser - UserSingleton.setUserInformations(emptyUser) - } else if(username.equals("gabrielalbino")) { - returnedUser = UserSingleton.getUserInformations() } val response: ShowProfileModel.Response = ShowProfileModel.Response(returnedUser) diff --git a/project/app/src/main/java/com/nexte/nexte/UserSingleton.kt b/project/app/src/main/java/com/nexte/nexte/UserSingleton.kt index d16e6c08..bd770c45 100644 --- a/project/app/src/main/java/com/nexte/nexte/UserSingleton.kt +++ b/project/app/src/main/java/com/nexte/nexte/UserSingleton.kt @@ -6,12 +6,12 @@ package com.nexte.nexte */ object UserSingleton { - private const val ageConstant = 19 - private const val rankConstant = 15 - private var userInformations: Player = Player("gabrielalbino", + private const val ageConstant = 25 + private const val rankConstant = 12 + private var userInformations: Player = Player("Nick Cairo", rankConstant, "imgur.com/nudh486d4", - "enggabriel@gmail.com", + "cairo@nexte.com", "masculino", "ASCAD", ageConstant, diff --git a/project/app/src/main/res/layout/activity_main.xml b/project/app/src/main/res/layout/activity_main.xml index 7ef2dd69..cc8b55ea 100644 --- a/project/app/src/main/res/layout/activity_main.xml +++ b/project/app/src/main/res/layout/activity_main.xml @@ -15,6 +15,7 @@ android:layout_marginEnd="148dp" android:layout_marginStart="148dp" android:layout_marginTop="16dp" + android:visibility="invisible" android:text="LOGIN" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -34,27 +35,17 @@ + app:layout_constraintVertical_bias="1.0"> -