By continuing you indicate that you have read and agree to our Terms of service and Privacy policy
by square Kotlin Version: 2.8 License: Apache-2.0
by square Kotlin Version: 2.8 License: Apache-2.0
Support
Quality
Security
License
Reuse
kandi's functional review helps you automatically verify the functionalities of the libraries and avoid rework.
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here
Get all kandi verified functions for this library.
Get all kandi verified functions for this library.
A powerful image downloading and caching library for Android
QUESTION
When I Update my Phone to Android 12, Installation did not succeed. The application could not be installed: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED
Asked 2022-Mar-07 at 12:31I was working on my project perfectly since I Update my phone to Android 12 unfortunately when I run the project to my phone this Error appears:
Installation did not succeed. The application could not be installed: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED
List of apks: [0] 'C:\Users\Microsoft\AndroidStudioProjects\YmmyServer\app\build\outputs\apk\debug\app-debug.apk' Installation failed due to: 'null' Retry
This is My build.gradle(Project) File:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.tools.build:gradle:4.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
And this is My build.gradle(Module) File:
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 32
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.ymmyserver"
minSdkVersion 30
targetSdkVersion 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation 'com.github.jd-alexander:android-flat-button:v1.1'
// implementation 'info.hoang8f:fbutton:1.0.5'
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.firebase:firebase-storage'
implementation 'com.firebaseui:firebase-ui-database:8.0.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
implementation 'com.google.firebase:firebase-core:10.2.0'
implementation 'com.google.firebase:firebase-database'
implementation 'com.google.firebase:firebase-analytics'
implementation platform('com.google.firebase:firebase-bom:29.1.0')
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
And this is the Mainifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ymmyserver">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Ymmy">
<activity android:name=".FoodList"></activity>
<activity
android:name=".Home"
android:label="@string/title_activity_home"
android:theme="@style/Theme.Ymmy.NoActionBar"></activity>
<activity android:name=".SignIn" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
What Should I do Please Help Me
ANSWER
Answered 2022-Mar-07 at 11:04Solved by Adding android:exported="true" on the main Activity in Mainifest File:
<activity android:name=".MainActivity"
android:exported="true">
QUESTION
Android Build Error: "lStar not found..."
Asked 2022-Feb-18 at 06:59I have error like this after trying to build my apps in Emulator
/Users/joel/.gradle/caches/transforms-3/06231cc1265260b25a06bafce7a4176f/transformed/core-1.7.0-alpha02/res/values/values.xml:105:5-114:25: AAPT: error: resource android:attr/lStar not found.
I don't know what causes this error. After digging some answer which has similarly error (but in flutter) Problem. But still not solved my issue.
I have this dependency in my project
buildscript {
repositories {
google()
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
}
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.firebase.crashlytics'
repositories {
maven { url 'https://maven.fabric.io/public' }
maven { url 'https://maven.google.com' }
maven { url "https://teads.jfrog.io/artifactory/SDKAndroid-maven-prod"}
mavenCentral()
}
android {
compileSdkVersion 29
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "mobile.apps.my"
minSdkVersion 17
targetSdkVersion 29
multiDexEnabled true
versionCode 152
versionName "8.1.7"
vectorDrawables.useSupportLibrary = true // This line hereP
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
dataBinding {
enabled = true
}
buildTypes {
debug {
firebaseCrashlytics {
mappingFileUploadEnabled false
}
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('androidx.test.espresso:espresso-core:3.2.0-beta01', {
exclude group: 'com.android.support', module: 'support-annotations'
})
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.4.0-alpha03'
implementation "androidx.appcompat:appcompat-resources:1.4.0-alpha03"
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation 'com.google.android.gms:play-services-analytics:17.0.0'
implementation 'it.sephiroth.android.library.imagezoom:imagezoom:2.3.0'
testImplementation 'org.json:json:20140107'
implementation 'com.comscore:android-analytics:6.1.0'
implementation 'com.android.support:customtabs:29.0.0'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'com.android.support:customtabs:29.0.0'
// Kodein Dependency Injection
implementation 'org.kodein.di:kodein-di-generic-jvm:6.2.1'
implementation 'org.kodein.di:kodein-di-framework-android-x:6.2.1'
// RETROFIT
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-scalars:2.1.0' // for test String
// Room components
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
androidTestImplementation "androidx.room:room-testing:2.2.5"
// Lifecycle components
implementation 'android.arch.lifecycle:extensions:1.1.1'
implementation 'androidx.paging:paging-runtime:2.1.2'
// UI
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'com.geniusforapp.fancydialog:FancyDialog:0.1.4'
implementation 'com.github.bluzwong:swipeback:0.2.0@aar'
implementation 'com.airbnb.android:lottie:3.6.0'
implementation 'com.veinhorn.scrollgalleryview:library:1.2.6'
implementation 'com.veinhorn.scrollgalleryview:picasso-loader:1.2.4'
implementation 'com.github.rubensousa:bottomsheetbuilder:1.6.1'
implementation "com.andkulikov:transitionseverywhere:1.8.1"
// HTTP LOGGING
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'org.jsoup:jsoup:1.13.1'
implementation 'androidx.multidex:multidex:2.0.1'
// ADS
implementation 'com.android.support:support-annotations:28.0.0'
// Required Dependency by Audience Network SDK
implementation 'com.google.android.gms:play-services-ads:19.7.0'
implementation 'com.google.android.gms:play-services-basement:17.6.0'
implementation("tv.teads.sdk.android:sdk:4.7.2@aar") {
transitive = true
}
implementation 'com.criteo.publisher:criteo-publisher-sdk:4.0.0'
implementation 'com.google.android.gms:play-services-ads-identifier:17.0.0'
implementation 'com.google.android.gms:play-services-base:17.6.0'
implementation ('com.facebook.android:audience-network-sdk:5.5.0'){
exclude group: 'com.google.android.gms'
}
implementation 'com.google.firebase:firebase-crashlytics:17.4.0'
implementation "androidx.core:core-ktx:1.6.0" // I have update this based on other solution
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// COROUTINES
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:2.5.0"
implementation 'com.github.mumayank:AirLocation:1.3.1'
androidTestImplementation 'androidx.test:rules:1.3.0-beta01'
implementation 'com.android.installreferrer:installreferrer:2.2'
//ANIMATION
implementation 'com.daimajia.androidanimations:library:2.4@aar'
implementation 'com.infideap.drawerbehavior:drawer-behavior:1.0.4'
implementation 'com.romandanylyk:pageindicatorview:1.0.3'
implementation 'org.ocpsoft.prettytime:prettytime:5.0.0.Final'
//SOCIAL
implementation 'com.google.android.gms:play-services-auth:19.0.0'
}
I have tried to upgrade version of androidx.core:core-ktx:1.6.0
then sync or invalidate cache/restart. But none of them give me good result. I am sure yesterday my project was alright with same dependency. Someone please help me, if this question unclear let me add more information. Thanks
ANSWER
Answered 2021-Sep-28 at 17:18I managed to fix this by upgrading compileSdk to 31 and kotlin gradle plugin to 1.5.10
compileSdk = 31
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10'
QUESTION
problem with the getting data from firestore into recyclerView
Asked 2022-Jan-08 at 14:10I am trying to implement a message page into my app. I take the messages from Firestore. When the user clicks on the RecyclerView item, isMessageRead value is changed to true. Everything is working but the problem is when read the boolean value from Firestore using model class, all of the values are coming false. what did I miss? thanks.
class NotificationAdapter(
var notificationList: List<NotificationModelClass>,
private val clickListener: (NotificationModelClass) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var notifications: List<NotificationModelClass> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val myView = LayoutInflater.from(parent.context)
.inflate(R.layout.notification_layout, parent, false)
return ChaplainsViewHolder(myView)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ChaplainsViewHolder).bind(notifications[position], clickListener)
}
override fun getItemCount(): Int {
return notifications.size
}
fun submitList(notificationList: List<NotificationModelClass>) {
notifications = notificationList
}
class ChaplainsViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val notificationTitle = itemView.title
private val notificationMessage = itemView.message
private val notificationTime = itemView.messageTime
private val notificationImage = itemView.logo
private val notificationCardView = itemView.notificationCardView
private val notificationMessageRead = itemView.imageViewMessageRead
fun bind(
notificationInfo: NotificationModelClass,
clickListener: (NotificationModelClass) -> Unit
) {
notificationTitle.text = notificationInfo.title
notificationMessage.text = notificationInfo.body
val messageTime = notificationInfo.dateSent
val dateFormatLocalZone = SimpleDateFormat("HH:mm - MMM dd, yyyy")
dateFormatLocalZone.timeZone = TimeZone.getDefault()
val timeRangeFirst = dateFormatLocalZone.format(Date(messageTime!!.toLong()))
//notificationTime.text = timeRangeFirst.toString()
Picasso.get().load(R.drawable.logo).into(notificationImage)
notificationTime.text = notificationInfo.isMessageRead.toString()
/*if (isMessageRead == "no"){
notificationMessageRead.setImageResource(R.drawable.ic_baseline_mic_24)
}*/
notificationCardView.setOnClickListener {
clickListener(notificationInfo)
}
}
}
}
ANSWER
Answered 2022-Jan-08 at 14:10When you try to map a document into an object of type NotificationModelClass
it means that each field in the class will be initialized with the value of the corresponding field that exists in the document. Since the isMessageRead
field is already initialized with the value of false
, when deserializing the value of the field will always be false
. To solve this you have to change:
var isMessageRead: Boolean? = false,
To:
val isMessageRead: Boolean? = null,
In this way, you'll initialize the field with a value that comes from the database and not with the default one.
QUESTION
android project its getting some error related to ANDROID_SDK_HOME
Asked 2021-Dec-28 at 08:15(when i try to run the project )error is Build file 'C:\Users\jupun\Desktop\trid-7\codecanyon-22842942-trid-city-guide-android-native-with-admin-panel-firebase\Trid-Android-Package\Android code\Trid-CityGuide_v7\app\build.gradle' line: 1
A problem occurred evaluating project ':app'.
Failed to apply plugin 'com.android.internal.application'. ANDROID_SDK_HOME is set to the root of your SDK: C:\Users\jupun\AppData\Local\Android\Sdk ANDROID_SDK_HOME was meant to be the parent path of the preference folder expected by the Android tools. It is now deprecated.
gradle.build
apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'realm-android'
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.1'
// classpath 'io.fabric.tools:gradle:1.+'
// classpath "io.realm:realm-gradle-plugin:4.2.0"
classpath "io.realm:realm-gradle-plugin:5.11.0"
classpath 'com.google.gms:google-services:4.3.3'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0'
}
}
repositories {
mavenCentral()
jcenter()
google()
maven { url 'https://maven.fabric.io/public' }
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
}
}
android {
compileSdkVersion 28
buildToolsVersion '31.0.0'
defaultConfig {
applicationId "com.tripeka.travel" // "com.bpackingapp.vietnam.travel"// "com.traveeva.android"//"com.rwandadestinations.android"
// "com.traveeva.android"// "com.rhodes.guide" "com.rwandadestinations.android"
// com.bpackingapp.vietnam.travel
minSdkVersion 21
targetSdkVersion 28
versionCode 21
versionName "1.14"
multiDexEnabled true
resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
}
dexOptions {
jumboMode = true
javaMaxHeapSize "4g" //specify the heap size for the dex process
}
buildTypes {
release {
minifyEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android.txt')
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'mips', 'mips64', 'arm64-v8a'
universalApk false
}
}
}
}
packagingOptions {
// exclude "lib/arm64-v8a/librealm-jni.so"
// exclude "lib/armeabi/librealm-jni.so"
// exclude "lib/mips/librealm-jni.so"
// exclude "lib/x86_64/librealm-jni.so"
// exclude "lib/x86/librealm-jni.so"
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.firebase:firebase-crashlytics:17.2.1'
implementation 'com.google.firebase:firebase-analytics:17.5.0'
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
exclude group: 'com.android.support', module: 'support-annotations'
})
// List view animation
// Slider Image
// compile 'com.firebase:firebase-client-android:2.0.3+'
// compile('com.facebook.android:facebook-android-sdk:4.23.0')
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.0.0'
//
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.nhaarman.listviewanimations:lib-core:3.1.0@aar'
//
implementation 'com.nhaarman.listviewanimations:lib-manipulation:3.1.0@aar'
//
implementation 'com.nhaarman.listviewanimations:lib-core-slh:3.1.0@aar'
//
implementation 'com.google.android.gms:play-services:11.6.2'
implementation 'androidx.multidex:multidex:2.0.0'
implementation 'com.google.firebase:firebase-core:11.6.2'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.nineoldandroids:library:2.4.0'
implementation 'com.daimajia.slider:library:1.1.5@aar'
implementation 'com.google.firebase:firebase-auth:11.6.2'
implementation 'com.facebook.android:facebook-android-sdk:4.23.+'
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'
implementation 'pl.charmas.android:android-reactive-location:0.10@aar'
implementation 'com.google.android.gms:play-services-location:11.6.2'
implementation 'com.google.android.gms:play-services-places:11.6.2'
implementation 'io.reactivex:rxjava:1.2.0'
implementation 'com.github.zurche:open-weather-map-android-wrapper:v0.1'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// compile 'io.realm:realm-android:4.2.0'
implementation 'com.timehop.stickyheadersrecyclerview:library:[0.4.3]@aar'
implementation 'org.florescu.android.rangeseekbar:rangeseekbar-library:0.3.0'
implementation 'de.hdodenhof:circleimageview:2.1.0'
testImplementation 'junit:junit:4.12'
implementation 'org.solovyev.android.views:linear-layout-manager:0.5@aar'
implementation 'com.google.maps.android:android-maps-utils:0.5+'
implementation 'com.google.android.gms:play-services-ads:11.6.2'
}
// ADD THIS AT THE BOTTOM
apply plugin: 'com.google.gms.google-services'
ANSWER
Answered 2021-Sep-06 at 09:56Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
This error mostly occurs when you updated any library in gradle.build Try to rollback any latest library you updated.
QUESTION
react router v5 to v6 nested route not working
Asked 2021-Dec-09 at 18:01I've been trying to solve the following problem : I try to upgrade this Frontend Mentor project https://haydee75.github.io/galleria/ from React Router v5 to v6. I tried to replace the code between with :
<Routes>
<Route path="galleria" element={<Gallery datas={data} clickEvent={handleSlideShow} />} />
<Route path="/galleria/:urlPath" element={<Paint datas={data} />} />
</Routes>
but it does not work as when I am on a Paint page when clicking on next (or prev) button it adds url to the existing one so the route is wrong. I also tried :
<Routes>
<Route path="galleria" element={<Gallery datas={data} clickEvent={handleSlideShow} />}>
<Route path="/galleria/:urlPath" element={<Paint datas={data} />} />
</Route>
</Routes>
But it does not work either.
Below are relevant components :
import "./Gallery.scss";
import { Link } from "react-router-dom";
const Gallery = ({ datas, clickEvent }) => {
return (
<div className="Gallery">
{datas.map((data, index) => {
return (
<div key={index} className="thumbnail">
<Link to={"/galleria/" + data.urlPath} onClick={clickEvent}>
<img
className="image"
src={data.images.thumbnail}
alt={data.images.name}
/>
</Link>
</div>
);
})}
</div>
);
};
export default Gallery;
import { useState } from "react";
import { Link, useParams } from "react-router-dom";
import "./Paint.scss";
import Modal from "../Modal/Modal";
const Paint = ({ datas }) => {
let { urlPath } = useParams();
const paint = datas.find((data) => data.urlPath === urlPath);
const nextSlide = datas.indexOf(paint) + 1;
const prevSlide = datas.indexOf(paint) - 1;
const [showModal, setShowModal] = useState(false);
const handleModal = () => {
setShowModal(!showModal);
};
const color1 = "#000";
const color2 = "#ccc";
const indexPaint = datas.indexOf(paint) + 1;
const datasLenght = datas.length;
const blackLineWidth = Math.round((indexPaint * 100) / datasLenght);
const greyLineWidth = 100 - blackLineWidth;
return (
<div className="Paint">
{paint ? (
<>
<div className="container">
<div className="row main">
<div
className="main-image"
style={{
backgroundImage: `url("${paint.images.hero.large}")`,
}}
>
<div className="icon-view-image" onClick={handleModal}>
<span>View Image</span>
</div>
</div>
{showModal && (
<Modal
largeImage={paint.images.gallery}
altProp={paint.name}
closeModal={handleModal}
/>
)}
<div className="main-informations">
<div className="info">
<h1>{paint.name}</h1>
<p>{paint.artist.name}</p>
</div>
<div className="img-artist">
<img src={paint.artist.image} alt={paint.artist.name} />
</div>
</div>
</div>
<div className="row content">
<div className="date">
<span>{paint.year}</span>
</div>
<div className="description">
<p>{paint.description}</p>
<a
className="source"
href={paint.source}
target="_blank"
rel="noreferrer"
>
<span className="link-secondary">Got to source</span>
</a>
</div>
</div>
</div>
<div
className="progress-bar"
style={{
backgroundImage: `linear-gradient(to right, ${color1}, ${color1} ${blackLineWidth}%, ${color2} ${blackLineWidth}%, ${color2} ${greyLineWidth}%)`,
}}
></div>
<div className="footer">
<div className="column">
<h3>{paint.name}</h3>
<div className="artist-name">
<span>{paint.artist.name}</span>
</div>
</div>
<div className="column nav-links">
<span className="prev-btn">
{prevSlide <= -1 ? (
<span className="disable"></span>
) : (
<Link className="active" to={datas[prevSlide].urlPath}></Link>
)}
</span>
<span className="next-btn">
{nextSlide >= 15 ? (
<span className="disable"></span>
) : (
<Link className="active" to={datas[nextSlide].urlPath}></Link>
)}
</span>
</div>
</div>
</>
) : (
<p>{urlPath} is not a planet</p>
)}
</div>
);
};
export default Paint;
Here is App.js parent component rendering the routes
import data from "./data.json";
import "./App.scss";
import { Switch, Route } from "react-router-dom";
import Menu from "./components/Menu/Menu";
import Gallery from "./components/Gallery/Gallery";
import Paint from "./components/Paint/Paint";
import { useState } from "react";
const App = () => {
data.forEach((d) => {
d["urlPath"] = d.name.replace(/\s/g, "-");
});
const [slideShow, setSlideShow] = useState(true);
const handleSlideShow = () => {
setSlideShow(!slideShow);
};
return (
<div className="App">
<div>
<Menu datas={data} clickEvent={handleSlideShow} slideShow={slideShow} />
<Switch>
<Route exact path="/galleria">
<Gallery datas={data} clickEvent={handleSlideShow} />
</Route>
<Route path="/galleria/:urlPath">
<Paint datas={data} />
</Route>
</Switch>
</div>
</div>
);
};
export default App;
Then the data.json file from where data values are coming :
[
{
"name": "Starry Night",
"year": 1889,
"description": "Although The Starry Night was painted during the day in Van Gogh's ground-floor studio, it would be inaccurate to state that the picture was painted from memory. The view has been identified as the one from his bedroom window, facing east, a view which Van Gogh painted variations of no fewer than twenty-one times, including The Starry Night. \"Through the iron-barred window,\" he wrote to his brother, Theo, around 23 May 1889, \"I can see an enclosed square of wheat ... above which, in the morning, I watch the sun rise in all its glory.\"",
"source": "https://en.wikipedia.org/wiki/The_Starry_Night",
"artist": {
"image": "./assets/starry-night/artist.jpg",
"name": "Vincent Van Gogh"
},
"images": {
"thumbnail": "./assets/starry-night/thumbnail.jpg",
"hero": {
"small": "./assets/starry-night/hero-small.jpg",
"large": "./assets/starry-night/hero-large.jpg"
},
"gallery": "./assets/starry-night/gallery.jpg"
}
},
{
"name": "Girl with a Pearl Earring",
"year": 1665,
"description": "The painting is a tronie, the Dutch 17th-century description of a 'head' that was not meant to be a portrait. It depicts a European girl wearing an exotic dress, an oriental turban, and what was thought to be a very large pearl as an earring. In 2014, Dutch astrophysicist Vincent Icke raised doubts about the material of the earring and argued that it looks more like polished tin than pearl on the grounds of the specular reflection, the pear shape and the large size of the earring.",
"source": "https://en.wikipedia.org/wiki/Girl_with_a_Pearl_Earring",
"artist": {
"image": "./assets/girl-with-pearl-earring/artist.jpg",
"name": "Johannes Vermeer"
},
"images": {
"thumbnail": "./assets/girl-with-pearl-earring/thumbnail.jpg",
"hero": {
"small": "./assets/girl-with-pearl-earring/hero-small.jpg",
"large": "./assets/girl-with-pearl-earring/hero-large.jpg"
},
"gallery": "./assets/girl-with-pearl-earring/gallery.jpg"
}
},
{
"name": "Guernica",
"year": 1937,
"description": "The scene occurs within a room where, on the left, a wide-eyed bull stands over a grieving woman holding a dead child in her arms. In the center of the room a horse falls in agony with a large gaping hole in its side, as if it had just been run through by a spear or javelin. The horse appears to be wearing chain mail armor, decorated with vertical tally marks arranged in rows. A dead and dismembered soldier lies under the horse. The hand of his severed right arm grasps a shattered sword, from which a flower grows.",
"source": "https://en.wikipedia.org/wiki/Guernica_(Picasso)",
"artist": {
"image": "./assets/guernica/artist.jpg",
"name": "Pablo Picasso"
},
"images": {
"thumbnail": "./assets/guernica/thumbnail.jpg",
"hero": {
"small": "./assets/guernica/hero-small.jpg",
"large": "./assets/guernica/hero-large.jpg"
},
"gallery": "./assets/guernica/gallery.jpg"
}
},
{
"name": "Penitent Magdalene",
"year": 1625,
"description": "Penitent Magdalene is a painting by the Italian artist Artemisia Gentileschi. It hangs in Seville Cathedral. It has probably been in the cathedral since the late 17th century. The painting's first home was the collection of Fernando Enriquez Afan de Ribera, from 1626 to 1637. She returned to the subject later in the 1620s in Mary Magdalene as Melancholy.",
"source": "https://en.wikipedia.org/wiki/Penitent_Magdalene_(Artemisia_Gentileschi)",
"artist": {
"image": "./assets/penitent-magdalene/artist.jpg",
"name": "Artemisia Gentileschi"
},
"images": {
"thumbnail": "./assets/penitent-magdalene/thumbnail.jpg",
"hero": {
"small": "./assets/penitent-magdalene/hero-small.jpg",
"large": "./assets/penitent-magdalene/hero-large.jpg"
},
"gallery": "./assets/penitent-magdalene/gallery.jpg"
}
},
{
"name": "The Storm on the Sea of Galilee",
"year": 1633,
"description": "The painting, in vertical format, shows a close-up view of Christ's disciples struggling frantically against the heavy storm to regain control of their fishing boat. A huge wave beats the bow and rips the sail. One of the disciples is seen vomiting over the side. Another one, looking directly out at the viewer, is a self-portrait of the artist. Only Christ, depicted on the right, remains calm.",
"source": "https://en.wikipedia.org/wiki/The_Storm_on_the_Sea_of_Galilee",
"artist": {
"image": "./assets/the-storm-on-the-sea-of-galilee/artist.jpg",
"name": "Rembrandt"
},
"images": {
"thumbnail": "./assets/the-storm-on-the-sea-of-galilee/thumbnail.jpg",
"hero": {
"small": "./assets/the-storm-on-the-sea-of-galilee/hero-small.jpg",
"large": "./assets/the-storm-on-the-sea-of-galilee/hero-large.jpg"
},
"gallery": "./assets/the-storm-on-the-sea-of-galilee/gallery.jpg"
}
},
{
"name": "The Great Wave off Kanagawa",
"year": 1831,
"description": "The Great Wave off Kanagawa (Japanese: 神奈川沖浪裏, Hepburn: Kanagawa-oki Nami Ura, lit. \"Under the Wave off Kanagawa\"), also known as The Great Wave or simply The Wave, is a woodblock print by the Japanese ukiyo-e artist Hokusai. It was published sometime between 1829 and 1833 in the late Edo period as the first print in Hokusai's series Thirty-six Views of Mount Fuji. The image depicts an enormous wave threatening three boats off the coast in the Sagami Bay (Kanagawa Prefecture) while Mount Fuji rises in the background.",
"source": "https://en.wikipedia.org/wiki/The_Great_Wave_off_Kanagawa",
"artist": {
"image": "./assets/the-great-wave-off-kanagawa/artist.jpg",
"name": "Hokusai"
},
"images": {
"thumbnail": "./assets/the-great-wave-off-kanagawa/thumbnail.jpg",
"hero": {
"small": "./assets/the-great-wave-off-kanagawa/hero-small.jpg",
"large": "./assets/the-great-wave-off-kanagawa/hero-large.jpg"
},
"gallery": "./assets/the-great-wave-off-kanagawa/gallery.jpg"
}
},
{
"name": "Van Gogh Self-portrait",
"year": 1889,
"description": "This self-portrait was one of about 32 produced over a 10-year period, and these were an important part of his work as a painter; he painted himself because he often lacked the money to pay for models. He took the painting with him to Auvers-sur-Oise, near Paris, where he showed it to Dr. Paul Gachet, who thought it was \"absolutely fanatical\". Art historians are divided as to whether this painting or Self-portrait without beard is Van Gogh's final self-portrait. The art historians Ingo F. Walther and Jan Hulsker consider this to be the last.",
"source": "https://en.wikipedia.org/wiki/Van_Gogh_self-portrait_(1889)",
"artist": {
"image": "./assets/van-gogh-self-portrait/artist.jpg",
"name": "Vincent Van Gogh"
},
"images": {
"thumbnail": "./assets/van-gogh-self-portrait/thumbnail.jpg",
"hero": {
"small": "./assets/van-gogh-self-portrait/hero-small.jpg",
"large": "./assets/van-gogh-self-portrait/hero-large.jpg"
},
"gallery": "./assets/van-gogh-self-portrait/gallery.jpg"
}
},
{
"name": "The Sleeping Gypsy",
"year": 1897,
"description": "The Sleeping Gypsy (French: La Bohémienne endormie) is an 1897 oil painting by French Naïve artist Henri Rousseau (1844–1910). It is a fantastical depiction of a lion musing over a sleeping woman on a moonlit night. Rousseau first exhibited the painting at the 13th Salon des Indépendants, and tried unsuccessfully to sell it to the mayor of his hometown, Laval. Instead, it entered the private collection of a Parisian charcoal merchant where it remained until 1924, when it was discovered by the art critic Louis Vauxcelles.",
"source": "https://en.wikipedia.org/wiki/The_Sleeping_Gypsy",
"artist": {
"image": "./assets/the-sleeping-gypsy/artist.jpg",
"name": "Henri Rousseau"
},
"images": {
"thumbnail": "./assets/the-sleeping-gypsy/thumbnail.jpg",
"hero": {
"small": "./assets/the-sleeping-gypsy/hero-small.jpg",
"large": "./assets/the-sleeping-gypsy/hero-large.jpg"
},
"gallery": "./assets/the-sleeping-gypsy/gallery.jpg"
}
},
{
"name": "Lady with an Ermine",
"year": 1489,
"description": "The Lady with an Ermine (Italian: Dama con l'ermellino [ˈdaːma kon lermelˈliːno]; Polish: Dama z gronostajem) is a portrait painting widely attributed to the Italian Renaissance artist Leonardo da Vinci. Dated to c. 1489–1491, the work is painted in oils on a panel of walnut wood. Its subject is Cecilia Gallerani, a mistress of Ludovico Sforza (\"Il Moro\"), Duke of Milan; Leonardo was painter to the Sforza court at the time of its execution. It is one of only four surviving portraits of women painted by Leonardo, the others being Ginevra de' Benci, La Belle Ferronnière and the Mona Lisa",
"source": "https://en.wikipedia.org/wiki/Lady_with_an_Ermine",
"artist": {
"image": "./assets/lady-with-an-ermine/artist.jpg",
"name": "Leonardo da Vinci"
},
"images": {
"thumbnail": "./assets/lady-with-an-ermine/thumbnail.jpg",
"hero": {
"small": "./assets/lady-with-an-ermine/hero-small.jpg",
"large": "./assets/lady-with-an-ermine/hero-large.jpg"
},
"gallery": "./assets/lady-with-an-ermine/gallery.jpg"
}
},
{
"name": "The Night Café",
"year": 1888,
"description": "The Night Café (French: Le Café de nuit) is an oil painting created by Dutch artist Vincent van Gogh in September 1888 in Arles. Its title is inscribed lower right beneath the signature. The painting is owned by Yale University and is currently held at the Yale University Art Gallery in New Haven, Connecticut. The interior depicted is the Café de la Gare, 30 Place Lamartine, run by Joseph-Michel Ginoux and his wife Marie, who in November 1888 posed for Van Gogh's and Gauguin's Arlésienne; a bit later, Joseph Ginoux evidently posed for both artists, too.",
"source": "https://en.wikipedia.org/wiki/The_Night_Caf%C3%A9",
"artist": {
"image": "./assets/the-night-cafe/artist.jpg",
"name": "Vincent Van Gogh"
},
"images": {
"thumbnail": "./assets/the-night-cafe/thumbnail.jpg",
"hero": {
"small": "./assets/the-night-cafe/hero-small.jpg",
"large": "./assets/the-night-cafe/hero-large.jpg"
},
"gallery": "./assets/the-night-cafe/gallery.jpg"
}
},
{
"name": "The Basket of Apples",
"year": 1893,
"description": "The Basket of Apples (French: Le panier de pommes) is a still life oil painting by French artist Paul Cézanne, which he created c. 1893. The painting is particularly remarkable for its creative composition, which rejected realistic representation in favour of distorting objects to create multiple perspectives. This approach eventually influenced other art movements, including Fauvism and Cubism. It belongs to the Helen Birch Bartlett Memorial Collection of the Art Institute of Chicago.",
"source": "https://en.wikipedia.org/wiki/The_Basket_of_Apples",
"artist": {
"image": "./assets/the-basket-of-apples/artist.jpg",
"name": "Paul Cézanne"
},
"images": {
"thumbnail": "./assets/the-basket-of-apples/thumbnail.jpg",
"hero": {
"small": "./assets/the-basket-of-apples/hero-small.jpg",
"large": "./assets/the-basket-of-apples/hero-large.jpg"
},
"gallery": "./assets/the-basket-of-apples/gallery.jpg"
}
},
{
"name": "The Boy in the Red Vest",
"year": 1889,
"description": "Cézanne painted four oil portraits of this Italian boy in the red vest, all in different poses, which allowed him to study the relationship between the figure and space. The most famous of the four, and the one commonly referred to by this title, is the one which depicts the boy in a melancholic seated pose with his elbow on a table and his head cradled in his hand. It is currently held in Zürich, Switzerland. The other three portraits, of different poses, are in museums in the US",
"source": "https://en.wikipedia.org/wiki/The_Boy_in_the_Red_Vest",
"artist": {
"image": "./assets/the-boy-in-the-red-vest/artist.jpg",
"name": "Paul Cézanne"
},
"images": {
"thumbnail": "./assets/the-boy-in-the-red-vest/thumbnail.jpg",
"hero": {
"small": "./assets/the-boy-in-the-red-vest/hero-small.jpg",
"large": "./assets/the-boy-in-the-red-vest/hero-large.jpg"
},
"gallery": "./assets/the-boy-in-the-red-vest/gallery.jpg"
}
},
{
"name": "Arnolfini Portrait",
"year": 1434,
"description": "It is considered one of the most original and complex paintings in Western art, because of its beauty, complex iconography, geometric orthogonal perspective, and expansion of the picture space with the use of a mirror. According to Ernst Gombrich \"in its own way it was as new and revolutionary as Donatello's or Masaccio's work in Italy. A simple corner of the real world had suddenly been fixed on to a panel as if by magic ... For the first time in history the artist became the perfect eye-witness in the truest sense of the term\".",
"source": "https://en.wikipedia.org/wiki/Arnolfini_Portrait",
"artist": {
"image": "./assets/arnolfini-portrait/artist.jpg",
"name": "Jan van Eyck"
},
"images": {
"thumbnail": "./assets/arnolfini-portrait/thumbnail.jpg",
"hero": {
"small": "./assets/arnolfini-portrait/hero-small.jpg",
"large": "./assets/arnolfini-portrait/hero-large.jpg"
},
"gallery": "./assets/arnolfini-portrait/gallery.jpg"
}
},
{
"name": "Mona Lisa",
"year": 1503,
"description": "The Mona Lisa (/ˌmoʊnə ˈliːsə/; italian: La Gioconda [la dʒoˈkonda] or Monna Lisa [ˈmɔnna ˈliːza]) is a half-length portrait painting by Italian artist Leonardo da Vinci. Considered an archetypal masterpiece of the Italian Renaissance, it has been described as \"the best known, the most visited, the most written about, the most sung about, the most parodied work of art in the world\". The painting's novel qualities include the subject's enigmatic expression, the monumentality of the composition, the subtle modelling of forms, and the atmospheric illusionism.",
"source": "https://en.wikipedia.org/wiki/Mona_Lisa",
"artist": {
"image": "./assets/mona-lisa/artist.jpg",
"name": "Leonardo da Vinci"
},
"images": {
"thumbnail": "./assets/mona-lisa/thumbnail.jpg",
"hero": {
"small": "./assets/mona-lisa/hero-small.jpg",
"large": "./assets/mona-lisa/hero-large.jpg"
},
"gallery": "./assets/mona-lisa/gallery.jpg"
}
},
{
"name": "The Swing",
"year": 1767,
"description": "The painting depicts an elegant young woman on a swing. A smiling young man, hiding in the bushes on the left, watches her from a vantage point that allows him to see up into her billowing dress, where his arm is pointed with hat in hand. A smiling older man, who is nearly hidden in the shadows on the right, propels the swing with a pair of ropes. The older man appears to be unaware of the young man. As the young lady swings high, she throws her left leg up, allowing her dainty shoe to fly through the air.",
"source": "https://en.wikipedia.org/wiki/The_Swing_(Fragonard)",
"artist": {
"image": "./assets/the-swing/artist.jpg",
"name": "Jean-Honoré Fragonard"
},
"images": {
"thumbnail": "./assets/the-swing/thumbnail.jpg",
"hero": {
"small": "./assets/the-swing/hero-small.jpg",
"large": "./assets/the-swing/hero-large.jpg"
},
"gallery": "./assets/the-swing/gallery.jpg"
}
}
]
ANSWER
Answered 2021-Dec-09 at 18:01If I'm understanding your question/issue correctly, you want to render the Gallery
and Paint
components each on their own routes independently, and fix the slideshow linking from painting to painting. For this use the first routing snippet so they are independent routes and not nested.
<Routes>
<Route
path="galleria"
element={<Gallery datas={data} clickEvent={handleSlideShow} />}
/>
<Route path="/galleria/:urlPath" element={<Paint datas={data} />} />
</Routes>
Next, the reason the next painting's urlPath
is being appended as /galleria/Girl-with-a-Pearl-Earring/The-Great-Wave-off-Kanagawa
is because react-router-dom
v6 is capable of using absolute and relative paths. The difference between them is a leading "/"
character. Paths starting with "/"
are absolute paths, and without are relative.
Within Paint
the next/previous buttons/links are specifying only the next/previous data[index].uriPath
value instead of including the "/galleria"
absolute path prefix.
<div className="column nav-links">
<span className="prev-btn">
{prevSlide <= -1 ? (
<span className="disable"></span>
) : (
<Link className="active" to={datas[prevSlide].urlPath}></Link>
)}
</span>
<span className="next-btn">
{nextSlide >= 15 ? (
<span className="disable"></span>
) : (
<Link className="active" to={datas[nextSlide].urlPath}></Link>
)}
</span>
</div>
Here datas[prevSlide].urlPath
is a string value of the data element name, i.e. "Girl-with-a-Pearl-Earring"
, there is no leading "/"
so the link is treated as a relative link.
There are a couple ways to resolve:
Fix the relative linking, make the new path relative from the parent "directory":
A relative
<Link to>
value (that does not begin with/
) resolves relative to the parent route, which means that it builds upon the URL path that was matched by the route that rendered that<Link>
. It may contain..
to link to routes further up the hierarchy. In these cases,..
works exactly like the command-line cd function; each..
removes one segment of the parent path.
<Link
className="active"
to={`../${datas[prevSlide].urlPath}`}
>
</Link>
...
<Link
className="active"
to={`../${datas[nextSlide].urlPath}`}
>
</Link>
Use an absolute path:
<Link
className="active"
to={`/galleria/${datas[prevSlide].urlPath}`}
>
</Link>
...
<Link
className="active"
to={`/galleria/${datas[nextSlide].urlPath}`}
>
</Link>
QUESTION
Error extracting an `.aab` file: Invalid dex file indices, expecting file 'classes٢.dex' but found 'classes2.dex'
Asked 2021-Nov-27 at 19:02This error appears when I extract a file aab:
Invalid dex file indices, expecting file 'classes٢.dex' but found 'classes2.dex'.
my Gradle app:
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.rewardstom.win"
minSdkVersion 19
multiDexEnabled true
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
}
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries = false
}
}
dependencies {
implementation 'com.android.support:multidex:1.0.3'
implementation 'androidx.multidex:multidex:2.0.1'
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'])
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'androidx.palette:palette:1.0.0'
implementation 'com.android.volley:volley:1.2.0'
implementation 'com.facebook.android:facebook-login:7.1.0'
implementation platform('com.google.firebase:firebase-bom:28.2.0')
implementation 'com.google.firebase:firebase-auth'
implementation 'com.google.firebase:firebase-messaging'
implementation 'com.google.android.gms:play-services-auth:19.2.0'
implementation 'com.google.firebase:firebase-dynamic-links'
implementation "androidx.browser:browser:1.3.0"
//Ads
implementation 'com.google.android.gms:play-services-ads:20.2.0'
implementation 'com.google.android.gms:play-services-ads-identifier:17.0.1'
implementation 'com.google.android.gms:play-services-basement:17.6.0'
api 'com.tapjoy:tapjoy-android-sdk:12.8.0@aar'
implementation 'com.fyber:offerwall-sdk:9.2.2'
implementation 'com.applovin:applovin-sdk:10.2.1'
implementation 'com.adcolony:sdk:4.5.0'
implementation 'com.chartboost:chartboost-sdk:8.2.0'
implementation 'com.ironsource.sdk:mediationsdk:7.1.7'
implementation 'com.github.vungle:vungle-android-sdk:6.7.1'
implementation 'com.facebook.android:audience-network-sdk:6.5.1'
//noinspection GradleDependency
implementation 'commons-io:commons-io:2.4'
}
apply plugin: 'com.google.gms.google-services'
ANSWER
Answered 2021-Nov-24 at 21:35One temporary solution that may work is to set
release {
minifyEnabled false
.......
}
This will reduce your app size which may cause it to use only one dex file.
If this didn't work, you need to change your Windows display language to a language that uses. Arabic Numerals (including your Administrative language settings).
QUESTION
Navigate up from activity to fragment open the same fragment - Android Navigation Component
Asked 2021-Oct-07 at 13:41on this app, When I trying to navigate from "HomeFragment"
to "DetailsActivity"
then pressed back it's back to the same fragment and also the hamburger icon on click doesn't work
nav grpah
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/mobile_navigation"
app:startDestination="@id/nav_home">
<fragment
android:id="@+id/nav_home"
android:name="com.blogspot.abtallaldigital.ui.home.HomeFragment"
android:label="@string/home"
tools:layout="@layout/fragment_home"/>
<fragment
android:id="@+id/nav_Accessory"
android:name="com.blogspot.abtallaldigital.ui.accessory.AccessoryFragment"
android:label="@string/accessory"
tools:layout="@layout/fragment_accessory" />
<fragment
android:id="@+id/nav_Arcade"
android:name="com.blogspot.abtallaldigital.ui.arcade.ArcadeFragment"
android:label="@string/arcade"
tools:layout="@layout/fragment_arcade" />
<fragment
android:id="@+id/nav_Fashion"
android:name="com.blogspot.abtallaldigital.ui.fashion.FashionFragment"
android:label="@string/fashion"
tools:layout="@layout/fashion_fragment" />
<fragment
android:id="@+id/nav_Food"
android:name="com.blogspot.abtallaldigital.ui.food.FoodFragment"
android:label="@string/food"
tools:layout="@layout/food_fragment" />
<fragment
android:id="@+id/nav_Heath"
android:name="com.blogspot.abtallaldigital.ui.heath.HeathFragment"
android:label="@string/heath"
tools:layout="@layout/heath_fragment" />
<fragment
android:id="@+id/nav_Lifestyle"
android:name="com.blogspot.abtallaldigital.ui.lifestyle.LifestyleFragment"
android:label="@string/lifestyle"
tools:layout="@layout/lifestyle_fragment" />
<fragment
android:id="@+id/nav_Sports"
android:name="com.blogspot.abtallaldigital.ui.sports.SportsFragment"
android:label="@string/sports"
tools:layout="@layout/sports_fragment" />
<dialog
android:id="@+id/about"
android:name="com.blogspot.abtallaldigital.ui.about.AboutFragment"
android:label="about"
tools:layout="@layout/about" />
<activity
android:id="@+id/detailsActivity"
android:name="com.blogspot.abtallaldigital.ui.DetailsActivity"
android:label="activity_details"
tools:layout="@layout/activity_details" />
</navigation>
HomeFragment navigtion code
@Override
public void onViewCreated(@NonNull @NotNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.homeRecyclerView.addOnItemTouchListener(new RecyclerItemClickListener(requireContext(),
binding.homeRecyclerView, new RecyclerItemClickListener.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Item item = itemArrayList.get(position);
bundle.putParcelable("item",item);
Navigation.findNavController(requireView())
.navigate(R.id.detailsActivity, bundle,
new NavOptions.Builder()
.setPopUpTo(R.id.nav_home, true).build()
);
}
@Override
public void onLongItemClick(View view, int position) {
}
}
));
}
DetailsActivity
@AndroidEntryPoint
public class DetailsActivity extends AppCompatActivity {
private static final String TAG = "DetailsActivity";
private ActivityDetailsBinding binding;
String url, title, content, youtubeThumbnailImageSrc, youTubeLink;
int youtubeThumbnailImageSetVisibility;
private PostViewModel postViewModel;
private Item postItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDetailsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
postViewModel = new ViewModelProvider(this).get(PostViewModel.class);
postItem = getIntent().getParcelableExtra("item");
if (postItem != null) {
Log.d(TAG, "onItemClick: item" + postItem.getTitle());
final Document document = Jsoup.parse(postItem.getContent());
// final Elements elements = document.select("img");
Element element = document.body();
for (Element e : element.getElementsByClass
("YOUTUBE-iframe-video")) {
youtubeThumbnailImageSrc = e.attr("data-thumbnail-src");
youTubeLink = e.attr("src");
Log.e("YouTube thumbnail", youtubeThumbnailImageSrc);
Log.e("Youtube link", youTubeLink);
}
if (youtubeThumbnailImageSrc == null) {
youtubeThumbnailImageSetVisibility = 8;
}
url = postItem.getUrl();
title = postItem.getTitle();
content = postItem.getContent();
}
// blogImage = (ImageView) findViewById(R.id.blogImage);
setSupportActionBar(binding.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
binding.progressBar.setVisibility(View.VISIBLE);
binding.titleTextView.setText(title);
binding.blogContent.setMovementMethod(LinkMovementMethod.getInstance());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
binding.fab.bringToFront();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
binding.scrollView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
// Log.d("ScrollView","scrollX_"+scrollX+"_scrollY_"+scrollY+"_oldScrollX_"+oldScrollX+"_oldScrollY_"+oldScrollY);
if (scrollY > 0 && binding.fab.isShown()) {
binding.fab.hide();
} else if (scrollY < 22) {
binding.fab.show();
}
});
} else {
binding.scrollView.getViewTreeObserver().addOnScrollChangedListener(() -> {
int mScrollY = binding.scrollView.getScrollY();
if (mScrollY > 0 && binding.fab.isShown()) {
binding.fab.hide();
} else if (mScrollY < 22) {
binding.fab.show();
}
});
}
binding.fab.setOnClickListener(view -> {
String shareContent = title + "\n" + url;
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, shareContent);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
try {
startActivity(Intent.createChooser(shareIntent, title));
} catch (Exception exception) {
Log.e(TAG, "onCreate: " + exception);
}
});
// String imageSrc = getIntent().getStringExtra("blogImage");
// Glide.with(getApplicationContext()).load(imageSrc).into(blogImage);
binding.youtubeThumbnailImage.setVisibility(youtubeThumbnailImageSetVisibility);
binding.youtubeThumbnailImage.setAdjustViewBounds(true);
Picasso.get().load(youtubeThumbnailImageSrc).into(binding.youtubeThumbnailImage);
binding.youtubeThumbnailImage.setOnClickListener(view -> {
Intent youTube = new Intent
(Intent.ACTION_VIEW, Uri.parse(youTubeLink));
startActivity(youTube);
});
PicassoImageGetter imageGetter = new PicassoImageGetter(binding.blogContent, this);
Spannable html;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
html = (Spannable) Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY, imageGetter, null);
} else {
html = (Spannable) Html.fromHtml(content, imageGetter, null);
}
binding.blogContent.setText(html);
binding.visitSite.setOnClickListener(view -> openCustomTab(this, Uri.parse(url)));
binding.progressBar.setVisibility(View.GONE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_details_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_add_to_favorites) {
saveTogFavorites(item);
} else if (item.getItemId() == R.id.action_share) {
ShareActionProvider shareActionProvider =
(ShareActionProvider) MenuItemCompat.getActionProvider(item);
shareActionProvider.setShareIntent(createShareIntent());
return true;
} else if (item.getItemId() == R.id.copyTheLink) {
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clipData = ClipData.newPlainText("link", url);
clipboardManager.setPrimaryClip(clipData);
Toast.makeText(this, getString(R.string.linkCopied), Toast.LENGTH_LONG).show();
return true;
}
return super.onOptionsItemSelected(item);
}
private void saveTogFavorites(MenuItem menuItem) {
// Bundle bundle = getIntent().getParcelableExtra("postList");
FavoritesEntity favoritesEntity = new FavoritesEntity(0,
postItem);
postViewModel.insertFavorites(favoritesEntity);
menuItem.setIcon(R.drawable.ic_favorite);
Snackbar.make(binding.getRoot(), "Saved", Snackbar.LENGTH_LONG).show();
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
MainActivity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
@SuppressWarnings("unused")
private AppBarConfiguration mAppBarConfiguration;
public static Utils.DataStoreRepository DATA_STORE_REPOSITORY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
DATA_STORE_REPOSITORY = new Utils.DataStoreRepository(this);
setSupportActionBar(binding.appBarMain.toolbar);
mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_home, R.id.nav_Accessory,
R.id.nav_Arcade, R.id.nav_Fashion,
R.id.nav_Food, R.id.nav_Heath,
R.id.nav_Lifestyle, R.id.nav_Sports, R.id.about)
.setOpenableLayout(binding.drawerLayout)
.build();
NavHostFragment navHostFragment = (NavHostFragment)
getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
assert navHostFragment != null;
NavController navController = navHostFragment.getNavController();
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(binding.navView, navController);
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
While I searching for the solution of this issue, I saw the similar question and I use viewModel with MutableLiveData
but not to handle the events
ANSWER
Answered 2021-Oct-06 at 07:18you can try removing the fragment from the fragment manager like this:
Fragment fragmentByTag = getFragmentManager().
findFragmentByTag("Old fragment tag");
if (fragmentByTag != null) {
getFragmentManager().beginTransaction()
.remove(fragmentByTag).commit();
}
QUESTION
Firebase search by multiple queries and add to RecyclerView Android Studio
Asked 2021-Jul-30 at 08:23I'm attempting to replicate a search function in a messaging app with Firebase and display the results in a RecyclerView.
I would like to return users whose firstname, username, or lastname start with the search input text in the same recyclerview, in that order.
I am able to successfully search by one of the children, in this case I'm searching for a user's first name, but I'm really stuck as to how to add the results from the username and lastname, and in such a way that there is no duplication (e.g. if I search "A", a user with firstname "Anna" and lastname "Albury" doesn't appear twice.
Any and all help appreciated, thanks.
Activity searchUsers method:
private void searchUsers(String s){
searchInput = search_users.getText().toString();
FirebaseRecyclerOptions<Friends> retrievedFriends = new FirebaseRecyclerOptions.Builder<Friends>()
.setQuery(FriendsRef.orderByChild("refFirstName")
.startAt(searchInput).endAt(searchInput+"\uf8ff"), Friends.class)
.build();
FirebaseRecyclerAdapter<Friends, FriendsViewHolder> adapter =
new FirebaseRecyclerAdapter<Friends, FriendsViewHolder>(retrievedFriends) {
@Override
protected void onBindViewHolder(@NonNull @NotNull FriendsViewHolder holder, int position, @NonNull @NotNull Friends model) {
final String usersIDs = getRef(position).getKey();
UsersRef.child(usersIDs).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull @NotNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child("Details").hasChild("profileImage")) {
String userImage = dataSnapshot.child("Details").child("profileImage").child("imageUrl").getValue().toString();
String profileFirstName = dataSnapshot.child("Details").child("firstname").getValue().toString();
String profileLastName = dataSnapshot.child("Details").child("lastname").getValue().toString();
String profileStatus = dataSnapshot.child("Details").child("status").getValue().toString();
String profileName = profileFirstName + " " + profileLastName;
holder.userName.setText(profileName);
holder.userStatus.setText(profileStatus);
Picasso.get().load(userImage).into(holder.profileImage);
} else {
String profileFirstName = dataSnapshot.child("Details").child("firstname").getValue().toString();
String profileLastName = dataSnapshot.child("Details").child("lastname").getValue().toString();
String profileName = profileFirstName + " " + profileLastName;
holder.userName.setText(profileName);
}
}
@Override
public void onCancelled(@NonNull @NotNull DatabaseError databaseError) {
}
});
}
@NonNull
@NotNull
@Override
public FriendsViewHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.users_message_layout, parent, false);
return new FriendsViewHolder(view);
}
};
myFriendsList.setAdapter(adapter);
adapter.startListening();
}
Activity onCreate method
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_message);
//default function
myFriendsList = (RecyclerView) findViewById(R.id.new_message_friends_list);
myFriendsList.setLayoutManager(new LinearLayoutManager(this));
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
FriendsRef = FirebaseDatabase.getInstance().getReference().child("Users").child(currentUserID).child("Friends");
UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
//search function
search_users = findViewById(R.id.new_message_search_edittext);
search_users.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = search_users.length();
if (length > 0) {
searchUsers(s.toString());
} else {
cancelSearch();
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
Friends class:
public class Friends {
public String firstName, lastName, status, image, uid;
public Friends (){
}
public Friends(String firstName, String lastName, String status, String image, String uid) {
this.firstName = firstName;
this.lastName = lastName;
this.status = status;
this.image = image;
this.uid = uid;
}
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
public String getStatus() {return status;}
public void setStatus(String lastName) {this.status = status;}
public String getImage() {return image;}
public void setImage(String image) {this.image = image;}
public String getUid() {return uid;}
public void setUid(String uid) {this.uid = uid;}
ANSWER
Answered 2021-Jul-30 at 08:23According to your last comment:
What I'm looking for is a way to get around this by effectively search three times, once for first names, once for last names, and once for usernames, and collate the resulting users in a single RecyclerView.
In this case, you should perform three different queries and collect all the results using Tasks.whenAllSuccess() method:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query firstQuery = rootRef...
Query secondQuery = rootRef...
Query thirdQuery = rootRef...
Task firstTask = firstQuery.get();
Task secondTask = secondQuery.get();
Task thirdTask = thirdQuery.get();
Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask, thirdTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
@Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list
}
});
But remember, to avoid duplicates, add a name to the list only if it does not exist. Then simply pass the list to an adapter, and display only the results without duplicates in a RecyclerView.
QUESTION
Communication between ViewPager's host Fragment and ViewPager's Fragment item
Asked 2021-May-03 at 21:15I have a Fragment(InsiraDocumentosFragment
) that has a viewpager
and in that fragment I initialize an adapter(InsiraDocumentoAdapter
) to initialize the viewpager
.
The adapter(InsiraDocumentoAdapter
) initializes generic fragments (DocumentoFragment
) that I update dynamically, I can now update the image that is shown inside it, but I need to get the click on that image to either change it or to remove it, but this needs to be done in the Fragment that contains the viewpager
, because is in this fragment(InsiraDocumentosFragment
) that I have the viewmodel
that communicates with the database.
How can I watch from InsiraDocumentosFragment
the click on the imageview
of DocumentFragment
?
Here are my code samples.
class InsiraDocumentosFragment : Fragment() {
private lateinit var _view: View
private lateinit var _imgBack: ImageView
private lateinit var _viewpager: ViewPager
private lateinit var _imgCamera: ImageView
private lateinit var _footerTitle: TextView
private lateinit var _titles: List<String>
private lateinit var _files: MutableList<File?>
private lateinit var _viewModel: DocumentoViewModel
private lateinit var _viewModelProposta: PropostaViewModel
private lateinit var _viewModelArquivo: ArquivoViewModel
private lateinit var _adapter: InsiraDocumentoAdapter
private lateinit var _proposta: PropostaEntity
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_insira_documento, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_view = view
_imgBack = _view.findViewById(R.id.imgBack)
_viewpager = _view.findViewById(R.id.viewpager)
_imgCamera = _view.findViewById(R.id.cameraDocumento)
_footerTitle = _view.findViewById(R.id.footerTitle)
_files = mutableListOf(null, null, null)
_titles = listOf(getString(R.string.identidade), getString(R.string.comprovante_renda), getString(R.string.foto))
_adapter = InsiraDocumentoAdapter(_titles, _files, childFragmentManager)
_viewpager.adapter = _adapter
_viewModel = ViewModelProvider(
this,
DocumentoViewModel.DocumentoViewModelFactory(DocumentoRepositorio(AppDatabase.getDatabase(_view.context).documentoDao()))
).get(DocumentoViewModel::class.java)
_viewModelProposta = ViewModelProvider(
this,
PropostaViewModel.PropostaViewModelFactory(PropostaRepositorio(AppDatabase.getDatabase(_view.context).propostaDao()))
).get(PropostaViewModel::class.java)
_viewModelArquivo = ViewModelProvider(
this,
ArquivoViewModel.ArquivoViewModelFactory(ArquivoRepositorio(AppDatabase.getDatabase(_view.context).arquivoDao()))
).get(ArquivoViewModel::class.java)
addViewPagerListener()
onClickImgBack()
onClickImgCamera()
onClickFooterTitle()
val propostaStr = arguments?.getString(PROPOSTA)
if (!propostaStr.isNullOrBlank()) {
_proposta = jsonToObjProposta(propostaStr)
}
}
private fun addViewPagerListener() {
_viewpager.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
if (position == _viewpager.adapter!!.count - 1) {
_footerTitle.text = getString(R.string.concluir)
} else {
_footerTitle.text = getString(R.string.proximo)
}
updateViewPagerLayout(position)
}
})
}
private fun updateViewPagerLayout(currentPage: Int) {
when (currentPage) {
0 -> {
habilitaIndicadorPagina(_view.findViewById(R.id.primeiraPagina), _view.findViewById(R.id.imgPrimeiraPagina), R.drawable.primeira_pagina_selecionada)
desabilitaIndicadorPagina(_view.findViewById(R.id.segundaPagina), _view.findViewById(R.id.imgSegundaPagina), R.drawable.segunda_pagina_nao_selecionada)
desabilitaIndicadorPagina(_view.findViewById(R.id.terceiraPagina), _view.findViewById(R.id.imgTerceiraPagina), R.drawable.terceira_pagina_nao_selecionada)
}
1 -> {
desabilitaIndicadorPagina(_view.findViewById(R.id.primeiraPagina), _view.findViewById(R.id.imgPrimeiraPagina), R.drawable.primeira_pagina_nao_selecionada)
habilitaIndicadorPagina(_view.findViewById(R.id.segundaPagina), _view.findViewById(R.id.imgSegundaPagina), R.drawable.segunda_pagina_selecionada)
desabilitaIndicadorPagina(_view.findViewById(R.id.terceiraPagina), _view.findViewById(R.id.imgTerceiraPagina), R.drawable.terceira_pagina_nao_selecionada)
}
2 -> {
desabilitaIndicadorPagina(_view.findViewById(R.id.primeiraPagina), _view.findViewById(R.id.imgPrimeiraPagina), R.drawable.primeira_pagina_nao_selecionada)
desabilitaIndicadorPagina(_view.findViewById(R.id.segundaPagina), _view.findViewById(R.id.imgSegundaPagina), R.drawable.segunda_pagina_nao_selecionada)
habilitaIndicadorPagina(_view.findViewById(R.id.terceiraPagina), _view.findViewById(R.id.imgTerceiraPagina), R.drawable.terceira_pagina_selecionada)
}
}
}
private fun desabilitaIndicadorPagina(layout: ConstraintLayout, image: ImageView, imageDrawable: Int) {
layout.setBackgroundResource(R.drawable.not_selected_indicator)
image.setBackgroundResource(imageDrawable)
}
private fun habilitaIndicadorPagina(layout: ConstraintLayout, image: ImageView, imageDrawable: Int, ) {
layout.setBackgroundResource(R.drawable.indicador_selecionado)
image.setBackgroundResource(imageDrawable)
}
private fun onClickFooterTitle() {
_footerTitle.setOnClickListener {
if (_viewpager.currentItem == _viewpager.adapter!!.count - 1) {
var success = true
for (i in 0..2) {
if (_files[i] == null || _files[i]?.path.isNullOrEmpty()) {
Toast.makeText(_view.context, R.string.favor_preencher_todas_as_fotos, Toast.LENGTH_LONG).show()
_viewpager.currentItem = i
success = false
break
}
}
if (success) {
_viewModelProposta.addProposta(_proposta.numeroProposta, _proposta.valorPropasta, _proposta.clienteId).observe(viewLifecycleOwner, { idProposta ->
_proposta.id = idProposta
_viewModel.addDocumento("Nome do Documento", _proposta.id).observe(viewLifecycleOwner, { idDocumento ->
val arquivos = mutableListOf<ArquivoEntity>()
for (i in 0..2) {
arquivos.add(ArquivoEntity(0, _files[i]!!.path, _titles[i], idDocumento))
}
_viewModelArquivo.addArquivos(arquivos).observe(viewLifecycleOwner, {
_view.findNavController().popBackStack(R.id.clienteFragment, false)
})
})
})
}
} else {
_viewpager.currentItem = _viewpager.currentItem + 1
}
}
}
private fun onClickImgBack() {
_imgBack.setOnClickListener {
_view.findNavController().navigateUp()
}
}
private fun onClickImgCamera() {
_imgCamera.setOnClickListener {
val intent = Intent(_view.context, ScannerActivity::class.java)
startActivityForResult(intent, REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
val mediaList = ScannerActivity.getOutputDirectory(_view.context).listFiles()?.toMutableList() ?: mutableListOf()
if (mediaList.size > 0) {
val documentoFile = mediaList[mediaList.size - 1]
_files.removeAt(_viewpager.currentItem)
_files.add(_viewpager.currentItem, documentoFile)
_adapter.notifyDataSetChanged()
}
}
}
private fun jsonToObjProposta(json: String): PropostaEntity {
val gson = Gson()
val arrayTutorialType = object : TypeToken<PropostaEntity>() {}.type
return gson.fromJson(json, arrayTutorialType)
}
override fun onResume() {
super.onResume()
_view = requireView()
}
companion object {
const val REQUEST_CODE = 1
const val IMAGE = "IMAGE"
const val ID_PROPOSTA = "ID_PROPOSTA"
const val PROPOSTA = "PROPOSTA"
}
}
class InsiraDocumentoAdapter(private val titles: List<String>, private var files: List<File?>, manager: FragmentManager): FragmentStatePagerAdapter(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getCount() = 3
override fun getItem(position: Int): Fragment {
return DocumentoFragment.newInstance(titles[position], files[position])
}
override fun getItemPosition(`object`: Any): Int {
return POSITION_NONE
}
}
class DocumentoFragment : Fragment() {
private lateinit var _view: View
private lateinit var _documento: ImageView
private lateinit var _documentoShape: ImageView
private lateinit var _txtTitle: TextView
private var _file: File? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.fragment_documento, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
_view = view
}
private fun setUpView() {
_documento = _view.findViewById(R.id.documento)
_documentoShape = _view.findViewById(R.id.documentoShape)
_txtTitle = _view.findViewById(R.id.txtTitle)
_txtTitle.text = arguments?.getString(TITLE)
if (!arguments?.getString(FILE).isNullOrEmpty()) {
_file = File(arguments?.getString(FILE))
}
onImgClick()
insereImagem()
}
private fun onImgClick() {
_documento.setOnClickListener {
if (_documentoShape.visibility == View.GONE && _file != null) {
val intent = Intent(_view.context, FullScreenActivity::class.java)
intent.putExtra(InsiraDocumentosFragment.IMAGE, _file?.path)
intent.putExtra(TITLE, _txtTitle.text)
startActivity(intent)
}
}
}
private fun insereImagem() {
if (_file != null) {
Picasso.get().load(_file!!).into(_view.findViewById<ImageView>(R.id.documento))
_view.findViewById<ImageView>(R.id.documentoShape)?.visibility = View.GONE
} else {
_view.findViewById<ImageView>(R.id.documentoShape)?.visibility = View.VISIBLE
}
}
override fun onResume() {
super.onResume()
setUpView()
}
companion object {
fun newInstance(title: String, file: File?): DocumentoFragment {
val fragmentFirst = DocumentoFragment()
val args = bundleOf(
TITLE to title,
FILE to file?.path
)
fragmentFirst.arguments = args
return fragmentFirst
}
const val TITLE = "TITLE"
const val FILE = "FILE"
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".documento.view.DocumentoFragment">
<TextView
android:id="@+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen_24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="Identidade"
android:textColor="#015669"
android:textSize="@dimen/dimen_20sp"
/>
<ImageView
android:id="@+id/documento"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#ffffff"
android:src="@drawable/rectangle_white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/txtTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:scaleType="fitXY"
android:layout_marginTop="@dimen/dimen_20dp"
android:contentDescription="@string/foto_documento"/>
<ImageView
android:id="@+id/documentoShape"
android:layout_width="88dp"
android:layout_height="101dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/document_shape"
android:contentDescription="@string/foto_documento"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".documento.view.InsiraDocumentosFragment"
android:background="#f0f0f0">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen_56dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/rectangle_blue_toolbar">
<ImageView
android:id="@+id/imgBack"
android:layout_width="@dimen/dimen_12dp"
android:layout_height="@dimen/dimen_20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginStart="@dimen/dimen_20dp"
android:layout_marginTop="18dp"
android:src="@drawable/tint_color"
android:contentDescription="@string/voltar"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/insira_os_documentos"
android:textColor="#ffffff"
android:textSize="@dimen/dimen_20sp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pagerIndicator"
android:layout_width="wrap_content"
android:layout_height="@dimen/dimen_30dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar"
android:layout_marginTop="@dimen/dimen_20dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/primeiraPagina"
android:layout_width="@dimen/dimen_30dp"
android:layout_height="@dimen/dimen_30dp"
android:background="@drawable/indicador_selecionado"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/segundaPagina"
android:layout_marginHorizontal="@dimen/dimen_10dp"
>
<ImageView
android:id="@+id/imgPrimeiraPagina"
android:layout_width="@dimen/dimen_9dp"
android:layout_height="@dimen/dimen_18dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@drawable/primeira_pagina_selecionada"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/segundaPagina"
android:layout_width="@dimen/dimen_30dp"
android:layout_height="@dimen/dimen_30dp"
android:background="@drawable/not_selected_indicator"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/primeiraPagina"
android:layout_marginHorizontal="@dimen/dimen_10dp"
>
<ImageView
android:id="@+id/imgSegundaPagina"
android:layout_width="@dimen/dimen_9dp"
android:layout_height="@dimen/dimen_18dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@drawable/segunda_pagina_nao_selecionada"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/terceiraPagina"
android:layout_width="@dimen/dimen_30dp"
android:layout_height="@dimen/dimen_30dp"
android:background="@drawable/not_selected_indicator"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/segundaPagina"
android:layout_marginHorizontal="@dimen/dimen_10dp"
>
<ImageView
android:id="@+id/imgTerceiraPagina"
android:layout_width="@dimen/dimen_9dp"
android:layout_height="@dimen/dimen_18dp"
android:layout_gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@drawable/terceira_pagina"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewpager"
android:layout_width="@dimen/dimen_280dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/pagerIndicator"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/footer"
android:layout_marginHorizontal="@dimen/dimen_40dp"
android:layout_marginTop="@dimen/dimen_20dp"
android:layout_marginBottom="@dimen/dimen_20dp"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/footer"
android:layout_width="match_parent"
android:layout_height="@dimen/dimen_69dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:background="@drawable/footer">
<ImageView
android:id="@+id/imgDocumento"
android:layout_width="@dimen/dimen_26dp"
android:layout_height="@dimen/dimen_30dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="@dimen/dimen_20dp"
android:layout_marginVertical="@dimen/dimen_20dp"
android:src="@drawable/combined_shape"
android:backgroundTint="#0179b0"
android:contentDescription="@string/formato_documento"
/>
<TextView
android:id="@+id/footerTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/imgDocumento"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@+id/cameraDocumento"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="@dimen/dimen_20sp"
android:textColor="#0179b0"
android:gravity="center"
android:text="@string/proximo"/>
<ImageView
android:id="@+id/cameraDocumento"
android:layout_width="@dimen/dimen_33dp"
android:layout_height="@dimen/dimen_30dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginEnd="@dimen/dimen_20dp"
android:layout_marginVertical="@dimen/dimen_20dp"
android:src="@drawable/camera_shape"
android:backgroundTint="#0179b0"
android:contentDescription="@string/capturar_foto"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
ANSWER
Answered 2021-May-03 at 21:12I need to get the click on that image to either change it or to remove it, but this needs to be done in the Fragment that contains the viewpager, because is in this fragment(InsiraDocumentosFragment) that I have the viewmodel that communicates with the database.
You have a couple of options to do that:
First one:
Make the ViewModel
shared between both fragments (InsiraDocumentosFragment
& DocumentoFragment
) by instantiating it in both fragments with the activity as the owner using requireActivity()
that hosts both fragments:
val viewModel =
ViewModelProvider(requireActivity()).get(MyViewModel::class.java)
And then no need to access the parent fragment for changing the image; because now you've an instance of the ViewModel
in the DocumentoFragment
.
Second one:
Access the InsiraDocumentosFragment
from the DocumentoFragment
using requireParentFragment()
, but first create a method in parent that you want to call from the page fragment to do your needed job.
Assuming the method that you created in InsiraDocumentosFragment
is someMethodInParent()
In DocumentoFragment
:
val parentFragment = requireParentFragment() as InsiraDocumentosFragment
parentFragment.someMethodInParent()
QUESTION
Initializing null object and pass between activities before saving
Asked 2021-Apr-08 at 12:01I am trying to do something which is very complicated to me.... I am trying to create an invoice with two objects 1) Invoice 2) InvoiceItems (Line Items)
The same activity is used to edit existing or to create a new invoice hence both Invoice and InvoiceItems are nullable.
The way I am trying to make this work is when the activity is launched,
The issues are two fold:
Please have a look at the code below:
class EditInvoice : AppCompatActivity() {
companion object {
@JvmStatic
fun start(context: Context, invoice: Invoice?, invoiceItems: InvoiceItems?) {
val starter = Intent(context, EditInvoice::class.java)
.putExtra("invoice", invoice)
.putExtra("invoiceItems", invoiceItems)
context.startActivity(starter)
}
}
private var invoice: Invoice? = null
private var invoiceEdit: Invoice? = null
private lateinit var contact: Contact
private var invoiceItems: List<InvoiceItems>? = null
private lateinit var dueDate: Calendar
private val calendar = Calendar.getInstance()
private var total = 0
private var subTotal = 0
private var taxrate = 0
private var invoiceType: String = ""
private var invoiceUpdt: InvoiceItems? = null
private var j: Int = 0
private var clientLkey: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_invoice)
val toolbar: Toolbar = findViewById(R.id.toolbar_editinv)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
dueDate = Calendar.getInstance()
//getting values from intent
invoice = intent.getSerializableExtra("invoice") as? Invoice
invoiceItems = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
invoiceUpdt = intent.getSerializableExtra("invoiceItemUpdt") as? InvoiceItems
j = intent.getIntExtra("i",0)
if (invoice == null){
invoiceType = "new"
edit_inv.text = "Add Invoice"
invoiceEdit = Invoice("0","0","0","0","0","0",0,0,null,"")
addinvoiceItem()
} else {
invoiceEdit = invoice
editInvoice()
}
//Setup Due date for the invoice
invoiceDueDt.setOnClickListener {
showCalendar()
}
//Auto complete based on database for selecting the client
val clientContact: List<Contact> = ArrayList<Contact>()
val adapter = ClientSelectAdapter(this, R.layout.userlatomcontacts, clientContact)
invoiceClient.setAdapter(adapter)
invoiceClient.threshold = 2
invoiceClient.setOnItemClickListener { parent, _, position, id ->
val selectedClient = parent.adapter.getItem(position) as Contact?
invoiceClient.setText(selectedClient?.name)
clientLkey = selectedClient?.lookupKey
}
val saveInvoice = findViewById<TextView>(R.id.editinv_save)
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
saveInvoice.setOnClickListener {
if(invoiceTitle.toString().isEmpty()){
Toast.makeText(this, "Invoice title can't be empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if(invoiceClient.toString().isEmpty()){
Toast.makeText(this, "Please select a Client for the invoice", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if(invoiceDueDt.toString().isEmpty()){
Toast.makeText(
this,
"Please enter the due date for the invoice",
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
if(invoiceItems == null){
Toast.makeText(
this,
"Please enter the line items/services for the invoice",
Toast.LENGTH_SHORT
).show()
return@setOnClickListener
}
//updating values as current
updateInvoiceValues()
//Storing values to DB
val db = AppDatabase.getDatabase(this)
if(invoiceType == "new"){
db.InvoicesDao().addInvoice(invoice!!)
for(i in invoiceItems!!.indices){
db.InvoiceItemsDao().addInvItem(invoiceItems!![i])
}
} else {
db.InvoicesDao().updateInvoice(invoice!!)
for(i in invoiceItems!!.indices){
db.InvoiceItemsDao().updateInvItem(invoiceItems!![i])
}
}
}
}
inner class ClientSelectAdapter(
context: Context,
@LayoutRes private val layoutResource: Int,
private var allContacts: List<Contact>
):
ArrayAdapter<Contact>(context, layoutResource, allContacts),
Filterable {private var mContact: List<Contact> = allContacts
override fun getCount(): Int {
return mContact.size
}
override fun getItem(p0: Int): Contact {
return mContact[p0]
}
override fun getItemId(p0: Int): Long {
// Or just return p0
return mContact[p0].id.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(parent.context)
.inflate(layoutResource, parent, false)
}
val invoiceClient = view!!.findViewById<View>(R.id.invClientName) as TextView
invoiceClient.text = mContact[position].name
val clientProfile = view.findViewById<View>(R.id.profile_image) as ShapeableImageView
Picasso.get().load(mContact[position].photoUri)
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(clientProfile)
val contLabel = view.findViewById<View>(R.id.salesLabelText) as TextView
if(mContact[position].label != null){
contLabel.text = mContact[position].label
if (mContact[position].label == "Lead" || mContact[position].label == "LEAD"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorPurple))
} else if (mContact[position].label == "Qualified"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorBlueNote))
} else if (mContact[position].label== "Proposal"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorMaroon))
} else if (mContact[position].label == "Client"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorGreen))
} else if (mContact[position].label == "Invoiced"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorYellow))
} else if (mContact[position].label == "Unpaid"){
contLabel.setBackgroundColor(resources.getColor(R.color.ColorRed))
} else if (mContact[position].label == ""){
salesLabel.visibility = View.GONE
}
}
return view
}
override fun getFilter(): Filter {
return object : Filter() {
override fun publishResults(
charSequence: CharSequence?,
filterResults: FilterResults
) {
mContact = filterResults.values as List<Contact>
notifyDataSetChanged()
}
override fun performFiltering(charSequence: CharSequence?): FilterResults {
var queryString = charSequence?.toString()?.toLowerCase(Locale.ROOT)
val results = FilterResults()
results.values = if (queryString == null || queryString.isEmpty())
allContacts
else {
queryString = "%${charSequence}%"
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
allContacts
}
return results
}
}
}
}
private fun showCalendar() {
val datePicker = DatePickerDialog(
this,
R.style.DateTimePickerTheme,
{ datePicker: DatePicker, year: Int, month: Int, day: Int ->
dueDate.set(year, month, day)
updateDateFields()
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
)
datePicker.show()
}
private fun updateDateFields() {
val formatter = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault())
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
if(dueDate.time < Calendar.getInstance().time)
{
Toast.makeText(this, "Please select a date that is today or later", Toast.LENGTH_SHORT).show()
} else {
invoiceDueDt.text = formatter.format(dueDate.time)
}
}
private fun editInvoice() {
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val itemOtherDetails = findViewById<EditText>(R.id.itemOtherDetails)
if(invoice!!.invoiceTitle != "0"){
invoiceTitle.setText(invoice!!.invoiceTitle)
}
if(invoice!!.invoiceClientLKey != "0"){
//getting client name from the database
val getClient = AppDatabase.getDatabase(this)
contact = getClient.contactsDao().getSingleContact(invoice!!.invoiceClientLKey!!)
invoiceClient.setText(contact.name)
}
if(invoice!!.othComments != "0"){
itemOtherDetails.setText(invoice!!.othComments)
}
addinvoiceItem()
invoiceClient.setOnClickListener{
val intent = Intent(this, ContactDetailsHome::class.java)
intent.putExtra("contact", contact as Serializable)
this.startActivity(intent)
}
}
private fun addinvoiceItem() {
val invoiceItemsLayout = findViewById<RelativeLayout>(R.id.invoiceItemsLayout)
val invoiceSubValue = findViewById<TextView>(R.id.invoiceSubValue)
val invoiceTaxValue = findViewById<TextView>(R.id.invoiceTaxValue)
val invoiceTotalValue = findViewById<TextView>(R.id.invoiceTotalValue)
if(invoice != null) {
if(intent.getSerializableExtra("invoiceItem") == null) {
//getting invoice items stored in the local db
val getItems = AppDatabase.getDatabase(this)
invoiceItems = getItems.InvoiceItemsDao().getinvItem(invoice!!.invNo)
}
for (i in invoiceItems!!.indices+1) {
//Check if invoiceItems have been received from EditBillingItems if yes, then update the particular object
if(j == i){
invoiceItems!![i].itemTitle = invoiceUpdt!!.itemTitle
invoiceItems!![i].itemDesc = invoiceUpdt!!.itemDesc
invoiceItems!![i].itemQty = invoiceUpdt!!.itemQty
invoiceItems!![i].itemRate = invoiceUpdt!!.itemRate
invoiceItems!![i].itemTaxable = invoiceUpdt!!.itemTaxable
invoiceItems!![i].itemTotal = invoiceUpdt!!.itemTotal
}
//Item Name Display on Invoice Activity
val itemTitle: ArrayList<TextView>? = null
itemTitle!![i] = TextView(this)
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
itemTitle[i].hint = "Enter Item Title"
itemTitle[i].textSize = 16f
itemTitle[i].layoutParams = layoutParams
itemTitle[i].setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle[i])
itemTitle[i].text = invoiceItems!![i].itemTitle
//Total Item Value
val itemValue: ArrayList<TextView>? = null
itemValue!![i] = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue[i].text = "00.00"
itemValue[i].textSize = 16f
itemValue[i].setTextColor(resources.getColor(R.color.txtcolor))
itemValue[i].setPadding(10, 0, 0, 10)
itemValue[i].layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue[i], layoutParams)
itemValue[i].text = invoiceItems!![i].itemTotal.toString()
if(invoiceItems!![i + 1].itemTitle == ""){
//New Item Title field
val itemTitle: ArrayList<TextView>? = null
itemTitle!![i] = TextView(this)
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
itemTitle[i].hint = "Enter Item Title"
itemTitle[i].textSize = 16f
itemTitle[i].setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle[i], layoutParams)
//New item value field
val itemValue: ArrayList<TextView>? = null
itemValue!![i] = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue[i].text = "00.00"
itemValue[i].textSize = 16f
itemValue[i].setTextColor(resources.getColor(R.color.txtcolor))
itemValue[i].setPadding(10, 0, 0, 10)
itemValue[i].layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue[i], layoutParams)
itemTitle[i].setOnClickListener {
val invoiceItemSend: InvoiceItems = invoiceItems!![i]
updateInvoiceValues()
val intent = Intent(this, EditBillingItem::class.java)
intent.putExtra("invoiceItem", invoiceItems as Serializable)
intent.putExtra("index", i)
intent.putExtra("invoice", invoice as Serializable)
this.startActivity(intent)
}
}
subTotal += invoiceItems!![i].itemTotal
val taxValue = invoiceItems!![i].itemRate!!
taxrate += (subTotal * taxValue)
}
invoiceSubValue.setText(subTotal)
total = subTotal + taxrate
invoiceTaxValue.setText(taxrate)
invoiceTotalValue.setText(total)
} else {
//Item Name Display on Invoice Activity
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams.setMargins(0, 0, 0, 0)
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START)
val itemTitle = TextView(this)
itemTitle.hint = "Enter Item Title"
itemTitle.textSize = 16f
itemTitle.setTextColor(resources.getColor(R.color.txtcolor))
invoiceItemsLayout.addView(itemTitle, layoutParams)
//Total Item Value
val itemValue = TextView(this)
val layoutParams2: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
) // or wrap_content
layoutParams2.setMargins(0, 0, 0, 0)
layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_END)
itemValue.text = "00.00"
itemValue.textSize = 16f
itemValue.setTextColor(resources.getColor(R.color.txtcolor))
itemValue.setPadding(10, 0, 0, 10)
itemValue.layoutParams = layoutParams2
invoiceItemsLayout.addView(itemValue, layoutParams2)
itemTitle.setOnClickListener {
updateInvoiceValues()
val intent = Intent(this, EditBillingItem::class.java)
if(invoiceItems != null){
intent.putExtra("invoiceItem", invoiceItems as Serializable)
}
if(invoice != null){
intent.putExtra("invoice", invoice as Serializable)
}
intent.putExtra("index",0)
this.startActivity(intent)
}
}
}
private fun updateInvoiceValues() {
//updating values
val invoiceTitle = findViewById<EditText>(R.id.invoiceTitle)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
if(invoiceTitle.text.toString().isNotEmpty()){
invoiceEdit?.invoiceTitle = invoiceTitle.text.toString()
}
if(clientLkey != ""){
invoiceEdit?.invoiceClientLKey = clientLkey
}
if (invoiceDueDt.text.toString().isNotEmpty()){
invoiceEdit?.dueDate = invoiceDueDt.text.toString()
}
}
ACTIVTY B - edit Item
class EditBillingItem : AppCompatActivity() {
companion object {
@JvmStatic
fun start(context: Context, invoice: Invoice?, invoiceItems: InvoiceItems?) {
val i = 0
val starter = Intent(context, EditInvoice::class.java)
.putExtra("invoice", invoice)
.putExtra("invoiceItem", invoiceItems)
.putExtra("i", i)
context.startActivity(starter)
}
}
private var invoiceItem: List<InvoiceItems>? = null
private var invoice: Invoice? = null
private lateinit var invoiceItemUpdt: InvoiceItems
private var i = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_billing_item_update)
invoice = intent.getSerializableExtra("invoiceEdit") as Invoice
invoiceItem = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
i = intent.getIntExtra("i", i)
val itemTitle = findViewById<EditText>(R.id.itemTitle)
val itemDesc = findViewById<EditText>(R.id.itemDesc)
val itemQty = findViewById<EditText>(R.id.itemQty)
val itemChrgRt = findViewById<EditText>(R.id.itemChrgRt)
val itemTaxable = findViewById<SwitchCompat>(R.id.itemTaxable)
val itemTotal = findViewById<TextView>(R.id.itemTotal)
val itemBack = findViewById<ImageButton>(R.id.itemBack)
if(intent.getSerializableExtra("invoiceItems") != null){
itemTitle.setText(invoiceItem!![i].itemTitle)
itemDesc.setText(invoiceItem!![i].itemDesc)
itemQty.setText(invoiceItem!![i].itemQty.toString())
itemChrgRt.setText(invoiceItem!![i].itemRate.toString())
itemTaxable.isChecked = invoiceItem!![i].itemTaxable == true
itemTotal.setText(invoiceItem!![i].itemTotal)
}
itemChrgRt.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int) {
if(s.toString().isNotEmpty() && itemQty.text.toString().isNotEmpty()){
var i = itemQty.text.toString().toInt()
val j = s.toString().toInt()
i *= j
itemTotal.text = i.toString()
}
}
})
itemQty.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int,
count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int,
before: Int, count: Int) {
if(itemChrgRt.text.toString().isNotEmpty() && itemChrgRt.text.toString().isNotEmpty()){
var i = s.toString().toInt()
val j = itemChrgRt.text.toString().toInt()
i *= j
itemTotal.text = i.toString()
}
}
})
itemBack.setOnClickListener {
if(itemTitle.toString().isBlank() && itemQty.toString().isNotBlank() || itemChrgRt.toString().isNotBlank() && itemTitle.toString().isBlank()){
Toast.makeText(this, "Title can't be empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
invoiceItemUpdt = InvoiceItems("0","0","0",null,null,null,null,0)
invoiceItemUpdt.itemTitle = itemTitle.toString()
invoiceItemUpdt.itemTitle = itemDesc.toString()
if(itemQty.toString().isEmpty()){
invoiceItemUpdt.itemQty = 1
} else {
invoiceItemUpdt.itemQty = itemQty.text.toString().toInt()
}
invoiceItemUpdt.itemRate = itemChrgRt.text.toString().toInt()
itemTaxable.isChecked = invoiceItemUpdt.itemTaxable == true
val intent = Intent(this, EditInvoice::class.java)
intent.putExtra("invoice", invoice as Serializable)
intent.putExtra("invoiceItem", invoiceItem as Serializable)
intent.putExtra("invoiceItemUpdt", invoiceItemUpdt as Serializable)
intent.putExtra("index", i)
this.startActivity(intent)
}
}
Error from logcat java.lang.NullPointerException: null cannot be cast to non-null type java.io.Serializable at in.latom.latom.Billing.ui.EditInvoice$addinvoiceItem$2.onClick(EditInvoice.kt:449) at android.view.View.performClick(View.java:7398) at android.view.View.performClickInternal(View.java:7375) at android.view.View.access$3700(View.java:817) at android.view.View$PerformClick.run(View.java:28516) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7858) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:984)
ANSWER
Answered 2021-Apr-08 at 08:16Your invoice
variable will be null if this line returns null:
invoice = intent.getSerializableExtra("invoice") as? Invoice
Later in your code, you had never populated your invoice
variable, but you force unwraps it in this line:
db.InvoicesDao().addInvoice(invoice!!)
This if statement always be null:
if(invoice != null){
intent.putExtra("invoice", invoice as Serializable)
}
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
No vulnerabilities reported
Save this library and start creating your kit
HTTPS
https://github.com/square/picasso.git
CLI
gh repo clone square/picasso
SSH
git@github.com:square/picasso.git
Share this Page
See Similar Libraries in
by opencv
by tesseract-ocr
by ageitgey
by naptha
by facebookresearch
See all Computer Vision Libraries
by square Kotlin
by square Java
by square Kotlin
by square Java
by square Kotlin
See all Libraries by this author
by opencv
by square
by thumbor
by albumentations-team
by pytorch
See all Computer Vision Libraries
by t-oster
by aspose-ocr
by ikkiChung
by neopoly
by wihoho
See all Computer Vision Libraries
by t-oster
by aspose-ocr
by theksmith
by ikkiChung
by neopoly
See all Computer Vision Libraries
by rmtheis
by aspose-ocr
by neopoly
by chrisbatt
by square
See all Computer Vision Libraries
by wihoho
by thiagokimo
by Paradoxis
by fedelemantuano
by dmici
See all Computer Vision Libraries
Save this library and start creating your kit
Open Weaver – Develop Applications Faster with Open Source