Floating Action Button not visible over Mapbox Android - android

It has been a while since I have developed an Android app. So current dev work is pretty new for me. I am trying to create a Mapbox Android API based app. So far I have successfully loaded User location and move camera based on location change; however, the FAB I have added on the layout is not showing up in either emulator or my phone. It is visible in the XML design view. I believe it might be due to the setContentView(mapView) in MapsActivity.kt which I don't know how is it not able to load the whole layout. Am I missing anything?
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.mapbox.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="40.7128"
mapbox:mapbox_cameraTargetLng="-74.0060"
mapbox:mapbox_cameraZoom="9.0">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:backgroundTint="#color/purple_200"
android:layout_margin="16dp"
android:contentDescription="#string/fab_description"
android:src="#drawable/ic_plus_icon"
tools:ignore="ImageContrastCheck" />
</com.mapbox.maps.MapView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MapsActivity.kt
package com.example.pinpoint
import android.Manifest
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.ActivityCompat
import com.example.pinpoint.com.example.pinpoint.LocationInitHelper
import com.example.pinpoint.com.example.pinpoint.LocationListeningCallback
import com.example.pinpoint.databinding.ActivityMapsBinding
import com.mapbox.android.core.location.LocationEngine
import com.mapbox.android.core.location.LocationEngineProvider
import com.mapbox.android.core.location.LocationEngineRequest
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.Style
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.maps.plugin.locationcomponent.location
import java.lang.ref.WeakReference
class MapsActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var locationEngine: LocationEngine
private val callback = LocationListeningCallback(this)
private lateinit var locationPermissionHelper: LocationPermissionHelper
private lateinit var locationInitHelper: LocationInitHelper
private lateinit var binding: ActivityMapsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMapsBinding.inflate(layoutInflater)
mapView = MapView(binding.root.context)
setContentView(mapView)
locationInitHelper = LocationInitHelper(WeakReference(this))
locationInitHelper.setMapView(mapView)
mapView.getMapboxMap().loadStyleUri(Style.MAPBOX_STREETS)
locationEngine = LocationEngineProvider.getBestLocationEngine(this)
locationPermissionHelper = LocationPermissionHelper(WeakReference(this))
onMapReady()
}
private fun onMapReady(){
val DEFAULT_INTERVAL_IN_MILLISECONDS = 1000L
val DEFAULT_MAX_WAIT_TIME = DEFAULT_INTERVAL_IN_MILLISECONDS * 5
locationEngine = LocationEngineProvider.getBestLocationEngine(this)
var request = LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_NO_POWER)
.setMaxWaitTime(DEFAULT_MAX_WAIT_TIME)
.build()
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
locationPermissionHelper.checkPermissions { onMapReady() }
}
locationEngine.requestLocationUpdates(request, callback, mainLooper)
locationEngine.getLastLocation(callback)
mapView.getMapboxMap().setCamera(
CameraOptions.Builder()
.zoom(12.0)
.build()
)
locationInitHelper.initLocationComponent()
locationInitHelper.setupGesturesListener()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onDestroy() {
super.onDestroy()
mapView.location
.removeOnIndicatorBearingChangedListener(locationInitHelper.onIndicatorBearingChangedListener)
mapView.location
.removeOnIndicatorPositionChangedListener(locationInitHelper.onIndicatorPositionChangedListener)
mapView.gestures.removeOnMoveListener(locationInitHelper.onMoveListener)
}
override fun onStop() {
super.onStop()
locationEngine.removeLocationUpdates(callback)
}
}

Try this
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.mapbox.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="40.7128"
mapbox:mapbox_cameraTargetLng="-74.0060"
mapbox:mapbox_cameraZoom="9.0">
</com.mapbox.maps.MapView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:backgroundTint="#color/purple_200"
android:layout_margin="16dp"
android:src="#drawable/ic_app_icon"
android:tint="#color/white"
tools:ignore="ImageContrastCheck" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Try declaring the floating action button outside the mapview like this:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.mapbox.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
mapbox:mapbox_cameraTargetLat="40.7128"
mapbox:mapbox_cameraTargetLng="-74.0060"
mapbox:mapbox_cameraZoom="9.0"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:backgroundTint="#color/purple_200"
android:layout_margin="16dp"
android:contentDescription="#string/fab_description"
android:src="#drawable/ic_plus_icon"
tools:ignore="ImageContrastCheck" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

I was able to solve this through MapsActivity.kt. As I suspected the setContentView() was getting the wrong view I replaced that part and assigned view manually to mapView. The script looks like this:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_maps)
mapView = findViewById(R.id.mapView)
locationInitHelper = LocationInitHelper(WeakReference(this))
locationInitHelper.setMapView(mapView)
mapView.getMapboxMap().loadStyleUri(Style.MAPBOX_STREETS)
locationEngine = LocationEngineProvider.getBestLocationEngine(this)
locationPermissionHelper = LocationPermissionHelper(WeakReference(this))
onMapReady()
}
Thanks for all the answers though!

Related

How use View.OnClickListener with FirestoreRecyclerAdapter

I'm trying to create an application and considering my level it's not easy! I hope you could help me since I didn't succeed with the many links I found on the internet.
I can't add the onClick function of View.OnClickListener, each time the Intent function is not recognized. I tried to implement it in the UserViewHolder and FirestoreRecyclerAdapter class but it doesn't work.
Here is my current code:
---------- kotlin part ---------
package edu.stanford.rkpandey.emojistatus
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.firebase.ui.firestore.FirestoreRecyclerAdapter
import com.firebase.ui.firestore.FirestoreRecyclerOptions
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import kotlinx.android.synthetic.main.activity_main.*
data class User(
val displayName: String? = "",
val emojis: String? = ""
)
class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
class MainActivity : AppCompatActivity() {
private val db = Firebase.firestore
private lateinit var auth: FirebaseAuth
// Query the users collection
private val query = db.collection("users")
val options = FirestoreRecyclerOptions.Builder<User>()
.setQuery(query, User::class.java)
.setLifecycleOwner(this).build()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = Firebase.auth
val adapter = object: FirestoreRecyclerAdapter<User, UserViewHolder>(options) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
val view = LayoutInflater.from(this#MainActivity).inflate(R.layout.item_pack, parent, false)
return UserViewHolder(view)
}
override fun onBindViewHolder(
holder: UserViewHolder,
position: Int,
model: User
) {
val tvName: TextView = holder.itemView.findViewById(R.id.title)
val tvEmojis: TextView = holder.itemView.findViewById(R.id.excerpt)
tvName.text = model.displayName
tvEmojis.text = model.emojis
}
}
rvUsers.adapter = adapter
rvUsers.layoutManager = LinearLayoutManager(this)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.miLogout) {
Log.i("MainActivity", "Logout")
auth.signOut()
val logoutIntent = Intent(this, LoginActivity::class.java)
logoutIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(logoutIntent)
}
return super.onOptionsItemSelected(item)
}
}
------- xml part -------
=> activity_main
<?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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvUsers"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
=> item_pack
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="100sp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="12sp"
android:layout_marginTop="12sp"
android:layout_marginEnd="12sp"
android:focusable="true"
android:clickable="true"
app:cardCornerRadius="10dp"
android:foreground="?android:attr/selectableItemBackground">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:background="#color/colorPack">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5sp"
style="#style/NoteTitleFont"
android:textColor="#color/colorTitle"
tools:text="Note 1" />
<TextView
android:id="#+id/excerpt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12sp"
android:layout_below="#id/title"
android:maxLines="1"
android:ellipsize="end"
android:textStyle="italic"
android:textColor="#color/colorDescribe"
tools:text="test text va se trouver ici, ça va contenir le début de la description du package." />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
This code gives this result :
I would like that when I click on one of the carviews it can go to the activity_pack_detail.
Do you know how to do Intent to PackDetailActivity?
I get this error no matter what I do =>
You're getting that error because you are calling Intent's class constructor with a wrong argument. The first argument should be a Context and not a View. The keyword this is referring in your code to a View and not to a context, hence the error.
To solve this, you have to pass a Context object like this:
val i = Intent(view.getContext(), PackDetailActivity::class.java)
And your error will go away.

Problems with webview

I'm creating an application that displays a webview and has a button that opens the Android settings. My problem is that when I add this button, the webview stops working and only show a white screen that doesn't charge. What am I doing wrong? I leave the code below:
PD: If I delete the code starting from "//init code" it works....
MainActivity.kt
package com.becas.apn_mexico
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import android.view.View
import com.becas.apn_mexico.base.BaseActivity
import com.becas.apn_mexico.databinding.ActivityMainBinding
import com.google.android.material.floatingactionbutton.FloatingActionButton
class MainActivity : BaseActivity<ActivityMainBinding>() {
companion object {
private const val URL_LINK_WEBSITE = "https://apn.tutorialez.net/index.php/landing-page/"
}
override fun setupViewBinding(): ActivityMainBinding {
return ActivityMainBinding.inflate(layoutInflater)
}
override fun setupViewModel() {
}
override fun setupUI(savedInstanceState: Bundle?) {
binding.mainWebview.loadUrlExt(URL_LINK_WEBSITE)
showAdBanner(binding.adsView.adsPhoneTabSpecialSmartBanner)
showAdInterstitial(getString(R.string.admob_interstitial))
}
// Init Code
private lateinit var fab: FloatingActionButton
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fab = findViewById(R.id.abrir_configuracion)
// Configurando el setonclicklistener
fab.setOnClickListener(View.OnClickListener{
val i = Intent(Settings.ACTION_APN_SETTINGS)
startActivity(i) })
}
}
ActivityMain.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="com.becas.apn_mexico.MainActivity">
<WebView
android:id="#+id/main_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/ads_view" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/abrir_configuracion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginRight="10dp"
android:layout_alignParentRight="true"
android:layout_above="#id/ads_view"
android:clickable="true"
android:backgroundTint="#color/colorPrimary"
android:contentDescription="#string/open_config_apn"
app:srcCompat="#drawable/ic_baseline_settings_24" />
<include
android:id="#+id/ads_view"
layout="#layout/ads_phone_tab_special_smart_banner" />
</RelativeLayout>
I think your problem is that you are not using the viewbinding to inflate your view:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// You need to get here the binding and put it into the ContentView method
val view = binding.root
setContentView(view)
fab = findViewById(R.id.abrir_configuracion)
// Configurando el setonclicklistener
fab.setOnClickListener(View.OnClickListener{
val i = Intent(Settings.ACTION_APN_SETTINGS)
startActivity(i) })
}
Alternatively, the problem is in your layout. Can you remove the
<include
android:id="#+id/ads_view"
layout="#layout/ads_phone_tab_special_smart_banner" />
From your layout and let me know if you get the expected result?

RecyclerView functions aren't called

I am trying to show a list of transactions in a recycler view.
Each transaction is represented by a CardView inside a constraint layout (see item_transaction.xml).
Somehow, the functions of my RecyclerView Adapter (onCreateViewHolder, onBindViewHolder and getItemCount) are never called (logs are never displayed - I removed most of them so the code is easier to read).
Therefore, the RecyclerView content doesn't display on my app.
It is also worth pointing out that I have a list of transactions called data in my adapter. Whenever I set the data in the list, it does update. No issues there.
💡 I know notifyDataSetChanged() isn't clean, I'll change it later on when I manage to get everything working.
Here is a preview of what I want so you can grasp the idea better :
EDIT : My fragment displays normally and has no problem executing code.
Hang on tight because there is a lot of code :
package com.example.manage.manageit.database
class Transaction(
var value: Long = 0,
var note: String = "",
var budget: String = "",
var creationTime: Long = System.currentTimeMillis()
)
Transaction.kt
package com.example.manage.manageit.home
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.manage.manageit.databinding.ActivityHomeBinding
import androidx.fragment.app.Fragment
import com.example.manage.manageit.R
import com.example.manage.manageit.about.AboutFragment
import com.example.manage.manageit.budget.TransactionFragment
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityHomeBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_home)
binding.bottomNavigation.menu.getItem(0).isCheckable = true
setFragment(HomeFragment())
binding.bottomNavigation.setOnItemSelectedListener {menu ->
when(menu.itemId){
R.id.homeFragmentButton -> {
setFragment(HomeFragment())
true
}
R.id.transactionFragmentButton -> {
setFragment(TransactionFragment())
true
}
R.id.aboutFragmentButton -> {
setFragment(AboutFragment())
true
}
else -> false
}
}
}
private fun setFragment(fr : Fragment){
val frag = supportFragmentManager.beginTransaction()
frag.replace(R.id.myNavHostFragment,fr)
frag.commit()
}
}
HomeActivity.kt : It contains a BottomNavigationView and my fragment.
package com.example.manage.manageit.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.adapters.TransactionAdapter
import com.example.manage.manageit.database.Transaction
import com.example.manage.manageit.databinding.FragmentHomeBinding
import java.util.logging.Logger
class HomeFragment : Fragment() {
private var logger = Logger.getLogger(HomeFragment::class.java.name)
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding: FragmentHomeBinding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_home,
container,
false
)
val recyclerView: RecyclerView = binding.transactionList
val transactionAdapter = TransactionAdapter()
recyclerView.adapter = transactionAdapter
recyclerView.layoutManager = LinearLayoutManager(context)
transactionAdapter.data = listOf(
Transaction(10, "Transaction note", "Groceries"),
Transaction(20, "Transaction note", "Groceries"),
Transaction(30, "Transaction note", "Groceries")
)
return inflater.inflate(R.layout.fragment_home, container, false)
}
}
HomeFragment.kt
package com.example.manage.manageit.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.manage.manageit.R
import com.example.manage.manageit.database.Transaction
import java.util.logging.Logger
class TransactionAdapter : RecyclerView.Adapter<TransactionViewHolder>() {
private var logger = Logger.getLogger(this::class.java.name)
var data = listOf<Transaction>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
logger.info("adapter : onCreateViewHolder()")
return TransactionViewHolder.from(parent)
}
override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) {
val item = this.data[position]
holder.bind(item)
}
override fun getItemCount(): Int {
logger.info("adapter : getItemCount()")
return this.data.size
}
}
class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val icon: ImageView = itemView.findViewById(R.id.transaction_icon)
private val note: TextView = itemView.findViewById(R.id.transaction_note)
private val value: TextView = itemView.findViewById(R.id.transaction_value)
fun bind(item: Transaction) {
icon.setImageResource(R.drawable.ic_dollar_sign)
note.text = item.note
value.text = item.value.toString()
}
companion object {
fun from(parent: ViewGroup): TransactionViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater
.inflate(R.layout.item_transaction, parent, false)
return TransactionViewHolder(view)
}
}
}
TransactionAdapter.kt
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context="com.example.manage.manageit.home.HomeActivity">
<RelativeLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/myNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"/>
</LinearLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/black"
android:paddingVertical="6dp"
app:itemIconSize="28dp"
app:itemIconTint="#color/nav_bar_item"
app:itemRippleColor="#color/ripple_color"
app:itemTextColor="#color/nav_bar_item"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/bottom_navigation_menu" />
</RelativeLayout>
</layout>
activity_home.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:fillViewport="true"
tools:context="com.example.manage.manageit.home.HomeFragment">
<TextView
android:id="#+id/homeActivityTitle"
style="#style/activityTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/medium_margin"
android:layout_marginTop="#dimen/medium_margin"
android:layout_marginEnd="#dimen/medium_margin"
android:text="#string/home_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/transaction_list"
android:layout_width="match_parent"
android:layout_height="400dp"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="#+id/floatingActionButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/homeActivityTitle" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="#dimen/medium_margin"
android:layout_marginBottom="#dimen/very_big_margin"
android:backgroundTint="#color/secondaryColor"
android:clickable="true"
android:contentDescription="#string/add_button_description"
android:src="#drawable/ic_plus"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:maxImageSize="32dp"
tools:ignore="RedundantDescriptionCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_home.xml
<?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="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
app:cardBackgroundColor="#android:color/transparent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/transaction">
<ImageView
android:id="#+id/transaction_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:contentDescription="Icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_dollar_sign"
app:tint="#android:color/white" />
<TextView
android:id="#+id/transaction_note"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:text="Transaction note"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/transaction_icon"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/transaction_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="30dp"
android:text="55€"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
item_transaction.xml : Basically a card view with an image and two text views (the transaction "note" and value).
In onCreateView, you have created your view layout twice. The first one you did using DataBindingUtil and that's the one whose RecyclerView you set up. But then you let that whole layout go back to the garbage collector because you create a brand new layout using layoutInflater and return that layout on the last line of onCreateView.
Technically, you should not be setting up views in onCreateView anyway. It should be done in onViewCreated(), although I don't think it makes much difference. However, since Fragment provides a constructor that can automatically inflate a provided layout ID, I think it's cleaner anyway to eliminate onCreateView() entirely, like this:
class HomeFragment : Fragment(R.layout.fragment_home) {
private var logger = Logger.getLogger(HomeFragment::class.java.name)
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
val binding: FragmentHomeBinding = DataBindingUtil.bind(view)
val recyclerView: RecyclerView = binding.transactionList
val transactionAdapter = TransactionAdapter()
recyclerView.adapter = transactionAdapter
recyclerView.layoutManager = LinearLayoutManager(context)
transactionAdapter.data = listOf(
Transaction(10, "Transaction note", "Groceries"),
Transaction(20, "Transaction note", "Groceries"),
Transaction(30, "Transaction note", "Groceries")
)
}
}

How to display a text view on CameraX preview view?

I want to display a text view in the preview view of camera. It will appear like a label on the camera preview. It should not affect the image. Just appear like a label on preview view. I tried using frame layout but the text view disappears on the preview view
Here's my layout
<?xml version="1.0" encoding="utf-8"?>
<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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<Button
android:id="#+id/camera_capture_button"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#drawable/ic_baseline_camera_24"
android:elevation="2dp"
android:layout_marginBottom="20dp"
android:scaleType="fitCenter"
android:layout_gravity="bottom|center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.926" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Hello"
android:textSize="25dp" />
<androidx.camera.view.PreviewView
android:id="#+id/viewFinder"
android:layout_width="379dp"
android:layout_height="576dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.camera.view.PreviewView>
</FrameLayout>
Main Activity
Here's the main logic->
package com.arpit.cameraxdemo
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
camera_capture_button.setOnClickListener {
takePhoto()
}
cameraExecutor = Executors.newSingleThreadExecutor()
}
private fun takePhoto() {
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewFinder.surfaceProvider)
}
imageCapture = ImageCapture.Builder().build()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
// checks the camera permission
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show()
finish()
}
}
}
companion object {
private const val TAG = "CameraXGFG"
private const val REQUEST_CODE_PERMISSIONS = 20
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
}
override fun onDestroy() {
super.onDestroy()
cameraExecutor.shutdown()
}
}
Try below code with RelativeLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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.camera.view.PreviewView
android:id="#+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:gravity="center"
android:text="CameraX" />
<Button
android:id="#+id/imageCaptureBtn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_margin="10dp"
android:gravity="center"
android:text="Click Image" />
</RelativeLayout>
Thanks for your help everyone. I have found the answer to my question. Actually what I was looking for is called overlay
viewFinder.overlay.add(tvText)
use the element "elevation" with 2dp

DropDownTextView Android change color

I using https://github.com/hakobast/DropdownTextView in version 0.1.1
version 0.3.1 is not suitable for me.
I'm wondering if it any chance to change the frame colour when I click DropdownTextView.
The second thing is how can I move the DropdownTextView title to the centre?
As you can see I have all gravity in centre mode and nothing happens.
My code:
MainActivity.kt
package com.example.myapplication
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.view.*
import android.widget.*
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.google.gson.Gson
import hakobastvatsatryan.DropdownTextView
class MainActivity : AppCompatActivity()
{
#RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var zwrotkaString = """{
}"""
var stat:Statistic = Gson().fromJson(zwrotkaString, Statistic::class.java)
val d = findViewById<ListView>(R.id.first_dropdown_text_view_list)
d.adapter = MyCustomAdapter(this#MainActivity, stat);
}
private class MyCustomAdapter(context: Context, stat: Statistic): BaseAdapter()
{
val statS:Statistic
private val mContext: Context
init
{
mContext = context
}
init
{
statS = stat
}
override fun getCount(): Int {
return statS.statisticsForGroups.size;
}
override fun getItem(position: Int): Any
{
return statS.statisticsForGroups[position];
}
override fun getItemId(position: Int): Long
{
return position.toLong();
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View
{
val layoutInflater = LayoutInflater.from(mContext);
val rowMain = layoutInflater.inflate(R.layout.rowlistviewstatistic, parent, false)
val statDropDownText = rowMain.findViewById<DropdownTextView>(R.id.dropdowntextrow)
statDropDownText.setTitleText("Title")
statDropDownText.setContentText("Content")
return rowMain
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start"
android:layout_gravity="center"
android:gravity="center"
>
<ListView
android:id="#+id/first_dropdown_text_view_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#android:color/transparent"
android:dividerHeight="20sp"
android:scrollbarStyle="insideInset"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewMain"
app:layout_constraintVertical_bias="0.403"
tools:ignore="MissingConstraints"
android:layout_gravity="center"
/>
</LinearLayout>
rowlistviewstatistic.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center"
android:layout_gravity="center"
android:orientation="vertical"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="qweqdasdasdasdadaq aa fadfeaeef"
/>
<hakobastvatsatryan.DropdownTextView
android:id="#+id/dropdowntextrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content_text_color="#color/purple_500"
app:arrow_drawable="#drawable/ic_arrow"
app:title_text_color="#color/colorRed"
android:layout_gravity="center"
android:gravity="center"
app:title_text_size="30sp"
app:bg_drawable_expanded="#drawable/answer_drawable"
android:clickable="true"
android:focusable="true"
/>
</LinearLayout>
answer_drawable.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#color/answer_border" />
<corners android:radius="5dp" />
</shape>
I'am wondering if it any chance to change frame color when I click DropdownTextView
Add OnClickListener to your TextView and once the user clicks it change the frame color
statDropDownText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
statDropDownText.setRegularBackgroundDrawableRes(R.drawable.answer_drawable)
}
});
Second thing is how can I move DropdownTextView title to center ?
After going through the source code I found this method getTitleTextView().
Calling this will return the TextView, and set gravity to center.
TextView ta = (TextView) getTitleTextView();
LayoutParams lp = new LayoutParams();
lp.gravity = Gravity.CENTER_HORIZONTAL;
ta.setLayoutParams(lp);
I fixed the 0.3.1 crash and released 0.3.3 please try and let me know if it fixes your problem.
I am not the owner of the library I forked it and fixed the crash and have to release it on jitpack rather than bintray(jcentre) as it deprecated.
Please find the detail for integrating the library at
https://stackoverflow.com/a/67520594/4828650

Categories

Resources