I want to make an application that calculates the differences between the current date and another date. I add "reset" button to change other date to current date. I want to save new date as default when i click button.
What can I do so that the changes I made do not go away when I restart the application and are permanent?
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DateDifferenceApp()
}
}
}
#Composable
fun DateDifferenceApp() {
val calendar = Calendar.getInstance().time
val currentDate1 = DateFormat.getDateInstance().format(calendar)
val time = DateFormat.getTimeInstance(DateFormat.SHORT).format(calendar)
val currentDate = remember { Calendar.getInstance().time }
var otherDate by remember {
mutableStateOf(
Calendar.getInstance().apply {
set(Calendar.YEAR, 2023)
set(Calendar.MONTH, Calendar.FEBRUARY)
set(Calendar.DAY_OF_MONTH, 12)
}.time
)
}
val diff = currentDate.time - otherDate.time
val diffInDays = TimeUnit.MILLISECONDS.toDays(diff)
val startingDate = DateFormat.getDateInstance().format(otherDate)
Button(onClick = { otherDate = currentDate },
modifier = Modifier.size(150.dp)
) {
Text("Reset",fontSize = 24.sp)
}
enter image description here
Related
I am trying to solve this issue but i didn#t find enything until now. So my Image View its a string and i am trying to call it with Glide.with and many more but unfortunately no success until now. It should be a simple Line of code but i am not finding it.
class ImageInformation : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_image_information)
val image = intent.getParcelableExtra<ImageModel>("image")
if (image != null){
val downloadUrl: TextView = findViewById(R.id.downloadUrla)
val previewUrl : ImageView = findViewById(R.id.previewUrls)
val id: TextView = findViewById(R.id.idsa)
val filename: TextView = findViewById(R.id.fileNamea)
val filesize: TextView = findViewById(R.id.filesizea)
val contentType: TextView = findViewById(R.id.contentTypea)
val createdBy: TextView = findViewById(R.id.createdBya)
val createdTimestamp: TextView = findViewById(R.id.createdTimestampa)
val creationSource: TextView = findViewById(R.id.creationSourcea)
val domainIdentityType: TextView = findViewById(R.id.domainIdentityTypea)
val domainIdentityValue: TextView = findViewById(R.id.domainIdentityValuea)
val tags: TextView = findViewById(R.id.tagsa)
val description: TextView = findViewById(R.id.descriptiona)
downloadUrl.text = image.downloadUrl
TO DO, Preview URL
//previewUrl.setImageResource(image.previewUrl)//Required Int not a String.
//Glide.with(this).load( previewUrl).into(previewUrl)
//Glide.with(Activity()).load(previewUrl).centerInside().into(previewUrl)
//previewUrl.setImageResource(image.previewUrl)
//Glide.with(Activity()).load(previewUrl).into(image.previewUrl)
//Glide.with(this).load(previewUrl).centerInside().into(image.previewUrl)
//previewUrl.setImageResource(image.previewUrl)
//Nothing from the above lines doesn#t work.
id.text = image.id
filename.text = image.fileName
filesize.text = image.filesize.toString()
contentType.text = image.contentType
createdBy.text = image.createdBy
createdTimestamp.text = image.createdTimestamp
creationSource.text = image.creationSource
domainIdentityType.text = image.domainIdentityType
domainIdentityValue.text = image.domainIdentityValue
tags.text = image.tags.toString()
description.text = image.description
}
}
}
Try this:
Glide.with(context)
.load(image.downloadUrl) // here we are telling Glide what it needs to load
.into(previewUrl) // here we are telling Glide where to load it into (your imageView)
I must say your naming of you ImageView (previewUrl) does make it very hard to read, it might be better to rename it to something like previewImageView.
I have been trying to code a step tracker app. When I build the app, it doesn't show any errors but when I run it, it crashes and throws this:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Float
at com.example.fitnesstracker.MainActivity.loadData(MainActivity.kt:159)
at com.example.fitnesstracker.MainActivity.onCreate(MainActivity.kt:48)
I have implemented everything that I need but it won't start.
Here is the code for the saveData() and loadData() where I have the error:
private fun saveData() {
val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putFloat("key1", previoustotalSteps)
editor.apply()
}
private fun loadData(){
val sharedPreferences= getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
val savedNumber = sharedPreferences.getFloat("key1", 0f)
Log.d("MainActivity", "$savedNumber")
previoustotalSteps = savedNumber
}
These lines are after the setContentView in the onCreate method:
loadData()
resetSteps()
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
And these are the other functions that I use:
override fun onSensorChanged(event: SensorEvent?) {
if(running){
val stepstaken = findViewById<TextView>(R.id.steps_taken_id)
val progressBar = findViewById<CircularProgressBar>(R.id.circularProgressBar)
totalSteps = event!!.values[0]
val currentSteps = totalSteps.toInt() - previoustotalSteps.toInt()
stepstaken.text = currentSteps.toString()
progressBar.apply {
setProgressWithAnimation(currentSteps.toFloat())
}
}
}
private fun resetSteps(){
val stepstaken = findViewById<TextView>(R.id.steps_taken_id)
stepstaken.setOnClickListener {
Toast.makeText(this, "Long tap for step reset.", Toast.LENGTH_SHORT).show()
}
stepstaken.setOnLongClickListener {
previoustotalSteps = totalSteps
stepstaken.text = 0.toString()
saveData()
true
}
}
Also the step counter doesn't work. It stays at 0 no matter how much I move my phone.
I tried to check issue with breakpoints but at this: "object : OnImageSavedCallback{
" line, debugger can't go further and just exits the function without any error. I hope someone can show me the part that I'm missing.
I also already added the permission requests to AndroidManifest.xml for writing and reading media on storage.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var imageCapture:ImageCapture? = null
private lateinit var outputDirectory: File
private lateinit var cameraExecutor:ExecutorService
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
outputDirectory = getOutputDirectory()
cameraExecutor = Executors.newSingleThreadExecutor()
if(allPermissionGranted()){
Toast.makeText(this, "Camera Permissions are Granted", Toast.LENGTH_SHORT).show()
startCamera()
}
else
{
ActivityCompat.requestPermissions(
this, Constants.REQUIRED_PERMISSIONS,
Constants.REQUEST_CODE_PERMISSIONS
)
}
binding.btnTakePhoto.setOnClickListener {
takePhoto()
}
}
private fun getOutputDirectory(): File{
val mediaDir = externalMediaDirs.firstOrNull()?.let { mFile ->
File(mFile, resources.getString(R.string.app_name)).apply {
mkdirs()
}
}
return if(mediaDir != null && mediaDir.exists())
mediaDir else filesDir
}
private fun takePhoto(){
val imageCapture = imageCapture?: return
val photoFile = File(
outputDirectory,
SimpleDateFormat(Constants.FILE_NAME_FORMAT,
Locale.getDefault()).format(System.currentTimeMillis()) + ".jpg")
val outputOption = ImageCapture.OutputFileOptions.Builder(photoFile).build()
imageCapture.takePicture(
outputOption, ContextCompat.getMainExecutor(this),
object : OnImageSavedCallback{
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
val savedUri = Uri.fromFile(photoFile)
val msg = "Photo Saved"
Toast.makeText(
this#MainActivity,
"$msg $savedUri",
Toast.LENGTH_LONG
).show()
}
override fun onError(exception: ImageCaptureException) {
Log.e(Constants.TAG, "onError: ${exception.message}",exception)
}
}
)
}
private fun startCamera(){
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
mPreview->
mPreview.setSurfaceProvider(
binding.viewFinder.surfaceProvider
)
}
imageCapture = ImageCapture.Builder().build()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try{
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)
}
catch (e: Exception){
Log.d(Constants.TAG, "startCamera Fail:", e)
}
}, ContextCompat.getMainExecutor(this))
}
#SuppressLint("MissingSuperCall")
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
if(requestCode == Constants.REQUEST_CODE_PERMISSIONS){
if(allPermissionGranted()){
startCamera()
}
else
{
Toast.makeText(this, "Permissions Not Granted by User", Toast.LENGTH_SHORT).show()
finish()
}
}
}
private fun allPermissionGranted() =
Constants.REQUIRED_PERMISSIONS.all{
ContextCompat.checkSelfPermission(
baseContext, it
) == PackageManager.PERMISSION_GRANTED
}
override fun onDestroy() {
super.onDestroy()
cameraExecutor.shutdown()
}
}
Emirhan.
I believe the error is in "outputOption".
Switch to this code and try to run the application and click the button.
Another thing, when trying to run the program and your app closes you can use the "Debug" to see which line of code is giving problem.
I hope it worked out, hug.
...
val outputFilesOption = ImageCapture.OutputFileOptions.Builder(photoFile).build()
imageCapture.takePicture(
outputFilesOption,getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
...
I'm trying to pass a constantly updating variable "message" across my Jetpack Composables. I have a draggable box that tracks the coordinates of the box but I'm trying to send the real-time data through a TCP connection. However, I noticed that the current coordinate of the draggable box isn't passing through to the other Composable or the socket -only the same value is passed despite message changing continuously due to me dragging the box. Also, the moment dataSendButton() is pressed, the createDragImage() and its draggable box stops animating/running.
var message = "" // global Android send message
class MainActivity : ComponentActivity() {
private var textView: TextView? = null
dataSendButton()
createDragImage()
...
}
}
}
#Composable
fun createDragImage(){
val context = LocalContext.current
...
Box() {
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.background(Color.Transparent)
.size(150.dp)
.border(BorderStroke(4.dp, SolidColor(Color.Red)))
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
offsetX = someConstantX
offsetY += dragAmount.y
message = offsetY.toString()
...
#Composable
fun dataSendButton() {
val context = LocalContext.current
...
Button(
onClick = {
// **ISSUE: message in this composable is not getting updated with message value from createDragImage()
val b1 = MainActivity.TCPconnector_client(context, message)
b1.execute()
},
{
Text(text = "Send Data", color = Color.White, fontSize = 20.sp)
}
}
}
}
}
It is because that is not how you store state in Compose.
Change the declaration of the variable.
var message by mutableStateOf(...)
Then the changes to it will trigger a recomposition, and so the rest of the code should remain the same. It is always recommended to store the state holders in a viewmodel, and pass the viewmodel around instead.
This is a working code with viewmodel
class MainActivity : ComponentActivity() {
private var textView: TextView? = null
val vm by viewmodels<MViewModel>()
dataSendButton(vm.message, vm:: onMessageChange)
createDragImage(vm.message)
...
}
}
}
#Composable
fun createDragImage(message: String, onMessageChange: (String) -> Unit){
val context = LocalContext.current
...
Box() {
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.background(Color.Transparent)
.size(150.dp)
.border(BorderStroke(4.dp, SolidColor(Color.Red)))
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
offsetX = someConstantX
offsetY += dragAmount.y
onMessageChange (offsetY.toString())
...
#Composable
fun dataSendButton(message: String) {
val context = LocalContext.current
...
Button(
onClick = {
// **ISSUE: message in this composable is not getting updated with message value from createDragImage() // This seems to be an error. Calling a Composable from onClick?
val b1 = MainActivity.TCPconnector_client(context, message)
b1.execute()
},
{
Text(text = "Send Data", color = Color.White, fontSize = 20.sp)
}
}
}
}
}
class MViewModel: ViewModel(){
var message by mutableStateOf("")
private set //do not allow external modifications to ensure consistency
fun onMessageChange (newMessage: String){
message = newMessage
}
}
Note this is the ideal way of doing such implementation. However, for your specific case, if you do not need to access it anywhere else, only changing the declaration as described in the second line of the answer should do
Thanks
I wrote a simple temperature converter app, everything is working fine except when user leaves EditText blank/null but selects one of the radio buttons, The App crashes.
Here is the Kotlin Code:
class MainActivity : AppCompatActivity() {
lateinit var etTemp: EditText
lateinit var radioGroup: RadioGroup
lateinit var btnConverter :Button
lateinit var tempConverted: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "Zeeshan's Temperature Converter"
etTemp = findViewById(R.id.etTemp)
radioGroup = findViewById(R.id.radioGroup)
btnConverter = findViewById(R.id.btnConverter)
tempConverted = findViewById(R.id.tempConverted)
btnConverter.setOnClickListener {
val id = radioGroup.checkedRadioButtonId
val radioButton = findViewById<RadioButton>(id)
if (radioButton == findViewById(R.id.radioC)){
val temp =etTemp.text.toString().toInt()
val result = temp * 9/5 + 32
tempConverted.setText(result.toString())
}
else if (radioButton == findViewById(R.id.radioF)){
val tempy =etTemp.text.toString().toInt()
val resulty = (tempy - 32) / 1.8
tempConverted.setText(resulty.toString())
}
else{
Toast.makeText(this#MainActivity, "Select one conversion scale", Toast.LENGTH_SHORT).show()
}
}
}
}
You should check if etTemp.text.ToString() == "" (that is empty string) if it is, then do not try to convert it into int. The problem appears when you try to convert "null" value to int.
Inside the listener add a check for for EditText to check whether it is empty or not,
btnConverter.setOnClickListener {
// Add the validation check here ... like this -> if(etTemp.length() > 0){
val id = radioGroup.checkedRadioButtonId
val radioButton = findViewById<RadioButton>(id)
if (radioButton == findViewById(R.id.radioC)){
val temp =etTemp.text.toString().toInt()
val result = temp * 9/5 + 32
tempConverted.setText(result.toString())
}
else if (radioButton == findViewById(R.id.radioF)){
val tempy =etTemp.text.toString().toInt()
val resulty = (tempy - 32) / 1.8
tempConverted.setText(resulty.toString())
}
else{
Toast.makeText(this#MainActivity, "Select one conversion scale", Toast.LENGTH_SHORT).show()
}
// Close the check here -> }
else{
// Prompt the user to put some text in the field - this is called form validation before processing
// Toast.makeText(.....).show
}
}
check if the user has entered some input or not, one way is like below (Kotlin):
if(!etTemp.text.isNullOrEmpty())
{
temp =etTemp.text.toString().toInt()
}