button click inside an item in recyclerview refreshes entire activity - firebase

I'm implementing a RecyclerView which has items which have a delete button, the data comes from Firebase and the delete button changes a "saved" value in firebase. this recyclerview is present in the third menu of the bottom navigation bar of the main activity.
When I click on the delete button, the entire activity restarts and the activity starts with the first menu of the bottom navigation bar
How do I stop this restarting action?
I'm attaching the RecyclerView adapter code below:
package com.demo.ash.demoapp
import android.content.Intent
import android.os.Environment
import android.support.v7.widget.RecyclerView
import android.transition.TransitionManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.FirebaseDatabase
import kotlinx.android.synthetic.main.offline_client.view.*
import kotlinx.android.synthetic.main.activity_main.*
import org.json.JSONObject
import java.io.File
/**
* Created by ashwin on 3/5/2018.
*/
class OfflineClientAdapter(val list: MutableList<Client>, val clientIDList:MutableList<String>): RecyclerView.Adapter<OfflineClientViewHolder>() {
lateinit var vg: ViewGroup
override fun getItemCount(): Int {
return list.size
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): OfflineClientViewHolder {
val layoutInflator = LayoutInflater.from(parent?.context)
vg = parent!!
val cellForRow = layoutInflator.inflate(R.layout.offline_client, parent, false)
return OfflineClientViewHolder(cellForRow, "")
}
override fun onBindViewHolder(holder: OfflineClientViewHolder?, position: Int) {
val row = list.get(position)
holder?.view?.NameView?.text = row.cname
holder?.view?.PhnumView?.text = row.cphonenum
holder?.clientID = clientIDList[position]
var encodedimage = IOHelper.stringToBitmap(row.cimage)
holder?.view?.client_image?.setImageBitmap(encodedimage)
val user = FirebaseAuth.getInstance().currentUser
var database = FirebaseDatabase.getInstance().getReference("Users").child(user?.phoneNumber)
.child("Clients").child(clientIDList[position])
holder?.view?.delete_client?.setOnClickListener {
val path = Environment.getExternalStorageDirectory()
val dir = File(path.toString() + "/pranjal/saved_clients.txt")
var clients = IOHelper.stringFromFile(dir)
var t = JSONObject(clients)
t.remove(clientIDList[position])
database.child("saved").setValue(false)
}
}
}
class OfflineClientViewHolder(val view: View, var clientID: String): RecyclerView.ViewHolder(view) {
init{
view.setOnClickListener {
val intent = Intent(view.context, OfflinePatientListActivity::class.java)
intent.putExtra("clientID",clientID)
view.context.startActivity(intent)
}
}
}

If you don't want to start an activity on button click, why do you have this code?
view.context.startActivity(intent)
?

When I click on the delete button, the entire activity restarts and the activity starts with the first menu of the bottom navigation bar
It kinda sounds like your Application is crashing. Unless you are doing something that would unintentionally (or intentionally?) restart said Activity.
It looks like you are changing the adapters data (deleting it) without calling the necessary methods to alert the adapter and recylerview that it needs to update its data. Make sure you call the necessary .notify...() methods after updating the data.
If the delete button is a part of the recylerview, make sure that you are taking it into account in the appropriate callbacks / code.
I’d make sure there aren’t any crashes going on in your
.delete_client?.setOnClickListener { ... }code.
Also make sure you aren’t accessing a null list in the other callbacks.
Hope this helps!

Related

Google SignIn with Android (kotlin) but NO pop up window to LogIn

I've been working recently in one of my projects in Android (kotlin), and in my LogIn page I was trying to implement the Google Sign In, for my surprise I was able to log in, but I can never see the typical pop up window that pops when you press the button to sign in (in my android app), it directly redirects me into gmail sign in in the browser, and then that's how I'm able to sign in, but never get to see the pop up.
I've tried changing some of the deprecated function, but never got anything (startActivityForResult)!
`This is my code:
package com.example.googlesignin
import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import android.widget.Toast import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.auth.api.signin.GoogleSignInOptions import com.google.android.gms.common.api.ApiException import com.google.android.material.snackbar.Snackbar import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.GoogleAuthProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import kotlinx.coroutines.withContext
const val REQUEST_CODE_SIGNIN = 21 class MainActivity : AppCompatActivity() {
lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
auth = FirebaseAuth.getInstance()
val googleButton = findViewById<Button>(R.id.googleButton)
googleButton.setOnClickListener {
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id_googleSignIn))
.requestEmail()
.build()
val signInClient = GoogleSignIn.getClient(this,options)
signInClient.signInIntent.also {
this.startActivityForResult(it, REQUEST_CODE_SIGNIN)
}
}
}
private fun googleAuthForFirebase(account: GoogleSignInAccount) {
val credentials = GoogleAuthProvider.getCredential(account.idToken,null)
CoroutineScope(Dispatchers.IO).launch {
try
{
auth.signInWithCredential(credentials).await()
withContext(Dispatchers.Main)
{
Toast.makeText(this#MainActivity,"Successfully Logged In",Toast.LENGTH_LONG).show()
}
}catch (e: java.lang.Exception)
{
withContext(Dispatchers.Main)
{
Toast.makeText(this#MainActivity,e.message,Toast.LENGTH_LONG).show()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == REQUEST_CODE_SIGNIN)
{
val account = GoogleSignIn.getSignedInAccountFromIntent(data).result
account?.let {
googleAuthForFirebase(it)
}
}
}
}
PD: I have only this activity and I have the xml of main_activity containing only one button to sign in. And I've done all the correct steps linking my project to firebase, if not I wouldn't be able to log in with my gmail account, but no pop up window.

I am trying to edit a thought in my thoughts app. I am not able to update it

package com.example.demo
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.activity_update_thought.*
class UpdateThoughtActivity : AppCompatActivity() {
private lateinit var thoughtDocumentId: String
lateinit var commentDocId: String
lateinit var thoughtTxt: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_update_thought)
thoughtDocumentId = intent.getStringExtra(THOUGHT_DOC_ID_EXTRA)!!
commentDocId = intent.getStringExtra(COMMENT_USER_ID_EXTRA)!!
thoughtTxt = intent.getStringExtra(COMMENT_TXT_EXTRA)!!
updateThoughtTxt.setText(thoughtTxt)
}
fun updateThoughtClicked(view: View) {
FirebaseFirestore.getInstance().collection(THOUGHTS_REF).document(thoughtDocumentId)
.update(THOUGHT_TXT, updateThoughtTxt.text.toString())
.addOnSuccessListener {
hideKeyboard()
finish()
}
.addOnFailureListener { exception ->
Log.e("Exception", "Could not update thought: ${exception.localizedMessage}")
}
}
private fun hideKeyboard() {
val inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
if (inputManager.isAcceptingText) {
inputManager.hideSoftInputFromWindow(currentFocus!!.windowToken,0)
}
}
}
Here I am trying to update the thought. I am not able to update it.When I click on update button during runtime. I see this error.
E Could not update thought: NOT_FOUND: No document to update: projects/fir-ee876/databases/(default)/documents/thoughts/null
I did for comments activity the same thing. It works fine. I am getting problem only for this.
Can you please help me with this?
I am trying to edit the thought and when I click on edit option it navigates to a new activity. In the new activity I want to update the thought and click on update button.When I click on that button the thought must be updated and must be displayed. When I tried this I am getting this error.
E Could not update thought: NOT_FOUND: No document to update: projects/fir-ee876/databases/(default)/documents/thoughts/null

Passing values from one fragment to another

I'm working in Kotlin and using retrofit. I have a recycler view, which consists of cards. Each card has a typeName and an image associated to it which for now I have added statically using dataclass. Now, I need to pass the typeName only from the CategoryFragment to the LocationFragment once the user clicks on a particular card. And at the LocationFragment I want to check the latitude, longitude and typeName from the database if it already exists.
Here's my code for the dataclass of Category:
data class Category_dataclass ( val category_image : Int , val typeName: String)
Here's my code for the CategoryFragment:
package com.example.atry.MakeComplaint
import android.content.Context
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.atry.History.Complaints
import com.example.atry.History.MyComplainRecyclerViewAdapter
import com.example.atry.R
import kotlinx.android.synthetic.main.existing_complaint_popup.*
class CategoryFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val v = inflater.inflate(R.layout.fragment_category, container, false)
val recyclerView = v.findViewById(R.id.category_list) as RecyclerView
recyclerView.apply {
layoutManager = GridLayoutManager(context!!, 2)
}
//creating an arraylist to store category using the data class user
val category = ArrayList<Category_dataclass>()
//adding some dummy data to the list of categories
category.add(Category_dataclass((R.drawable.trash) , "Water"))
category.add(Category_dataclass((R.drawable.fire) , "Sewerage"))
category.add(Category_dataclass((R.drawable.dustbin) , "load"))
//creating our adapter
val adapter = CategoryRecyclerViewAdapter(category)
//now adding the adapter to recyclerview
recyclerView.adapter = adapter
// Inflate the layout for this fragment
return v
}
}
Here's the CategoryRecyclerViewAdapter:
package com.example.atry.MakeComplaint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.atry.History.ComplaintDetailsFragment
import com.example.atry.History.Complaints
import com.example.atry.MakeComplaint.Category_dataclass
import com.example.atry.MakeComplaint.CategoryRecyclerViewAdapter
import com.example.atry.R
import java.util.*
import kotlin.collections.ArrayList
class CategoryRecyclerViewAdapter(val categoryList: ArrayList<Category_dataclass>) : RecyclerView.Adapter<CategoryRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CategoryRecyclerViewAdapter.ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.fragment_category_single, parent, false)
return ViewHolder(v)
}
//this method is binding the data on the list
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bindItems(categoryList[position])
holder.mView.setOnClickListener{view->
val lFragment = LocationFragment()
val oldFragment = CategoryFragment()
val manager = (holder.mView.context as AppCompatActivity).supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(
R.id.first_screen_of_makecomplaint,
lFragment
) // give your fragment container id in first parameter
transaction.show(lFragment)
transaction.hide(oldFragment)
transaction.isAddToBackStackAllowed
transaction.addToBackStack(oldFragment.fragmentManager.toString()) // if written, this transaction will be added to backstack
transaction.commit()
}
}
//this method is giving the size of the list
override fun getItemCount(): Int {
return categoryList.size
}
inner class ViewHolder(val mView : View) : RecyclerView.ViewHolder(mView) {
fun bindItems(cat:Category_dataclass) {
val imageViewName = mView.findViewById(R.id.category_image) as ImageView
val textViewtext = mView.findViewById(R.id.category_text) as TextView
imageViewName.setImageResource(cat.category_image)
textViewtext.text = cat.typeName
}
}
}
And this is my retrofit:
//to check existing complaint
#GET("api/existingComplain")
#FormUrlEncoded
fun checkExistingComplain(#Query("typeName") typeName:String,
#Query("longitude") longitude:String,
#Query("latitude") latitude:String):Observable<Observables.checkExistingResult>
I've created and object where i stored the dataclass which will return the following:
data class checkExistingResult(val description:String , val Complain:String)
if the typeName and location already exists in the database I want the description and Complain to be displayed on a material styled dialog.
You can try this:
1st Step:-
val dashboard = "Dashboard"
take variable like this you can take it's name as your fragment name so page name you can check like this MainActivity().dashboard
Now, 2nd Step:-
create one class and write function like this in that class
fun openPage(
activity: Activity,
pagename: String?, model: PaymentDetails
) {
when (pagename) {
MainActivity().dashboard -> {
val mfragment = DashboardFragment()
(activity as MainActivity).fragmentManager.beginTransaction()
.replace(R.id.nav_host, mfragment).commit()
val a = Bundle()
a.putSerializable("model", model)
mfragment.arguments = a
}
}
}
take key value pair as I take my whole model and key is model in my code you can write any thing.
3rd Step:-
Make your model Serializable
4th Step:- When you are adding your values into model add details and add your model for method in which you want to use these values like following
val payment = PaymentDetails(
type,
price,
name,
id,
)
paymentData!!.add(payment)
CustomMethods().openPagePaymentDetails(
activity!!,
MainActivity().sessionPaymentFragment, payment
)
5th Step:-
Declare and initialise your object with type of your model like following:
//Declare
private var model: PaymentDetails? = null
//initialise
model = arguments!!.getSerializable("model") as PaymentDetails?
And now finally you can access value of previous fragment into your next fragment like this,
var type: String
type = model!!.type
Note:- please do no forgot to make your model class Serializable
Hope so it will help you.

Link two Spinner with a button

I want the user to do this: when they select an item from the first spinner and the item on the other spinner and click on the button they get the result in a TextView. How can I do that?
I created already two spinner , TextView and one button. For example: if the user select from the first spinner their name and the second spinner their id, when they click to the button the text view will show their telephone number .
UPDATE:
Here is the code for the MainActivity
package second.program.p1;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.AdapterView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Spinner v1;
Spinner v2;
ArrayAdapter<CharSequence> adapter;
TextView T1;
Button b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
v1 = (Spinner) findViewById(R.id.v1);
adapter = ArrayAdapter.createFromResource(this,R.array.city_names,android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
v1.setAdapter(adapter);
v1.getSelectedItemPosition();
v2 = (Spinner) findViewById(R.id.v2);
adapter = ArrayAdapter.createFromResource(this,R.array.city_names,android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
v2.setAdapter(adapter);
T1 = (TextView) findViewById((R.id.T1));
b = (Button) findViewById(R.id.b);
}
};
Strings.xml
<resources>
<string name="app_name">P1</string>
<string-array name="city_names">
<item>" "</item>
<item>"Med"</item>
<item>"Ryu"</item>
<item>"Jedd"</item>
<item>"Hai"</item>
</string-array>
</resources>
So , i want after the user select "Med" from the first spinner (v1) and "Hai" from the second spinner (v2) he press the Button ,after that in the TextView will appers the km (the distance between the two cites, but i dont add it yet)
i did the two spinners ,
now what i should do with the TextView and the Button ?
As you have updated the question, so i can now answer it properly,
There are two methods that are provided by Android which we need to override to handle the items selection of spinners.
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// On selecting a spinner item
String cityName = parent.getItemAtPosition(position).toString();
// Showing selected spinner item
Toast.makeText(MainActivity, "Selected city: " + cityName, Toast.LENGTH_LONG).show();
}
public void onNothingSelected(AdapterView<?> view) {
// This method helps when we have to handle when user hasn't selected anything
from spinner on which further events are dependent.
}
Now do button click on your Button b like this in your onCreate:
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view){
String firstCityName = v1.getSelectedItem().toString();
String secondCityName = v2.getSelectedItem().toString();
//now you have both items/cities you selected from spinners
// so its time to do some checks and show user the distance
if(firstCityName.equals("Meh") && secondCityName.equals("Med"){
T1.setText("the value which you have stored somewhere");
} else if(firstCityName.equals("Med") && secondCityName.equals("Ryu"){
T1.setText("30KM / hardcode it or get the value you stored somewhere");
} //.... if-else-if for remaining cases
}
}
Some advices :
1- Please use proper naming conventions.
Spinner spinnerStartingCity = new .....
Button btnSubmit = new ....
2- Topics like these are not so hard to find over internet, first search properly, because what almost all coders DO ?? GOOGLE -> copy/paste !! :D
3- Before googling, if you want to be a Developer not just coder, first go through proper tutorials, android dev site, and online tutorials for thorough understanding because learning lasts longer than copy pasting :)
Happy Developing

creating submenu's in flex context menu

Is there any workaround to create submenu in a flex context menu other than stopping right click from javascript.
Regards,
Hi Frank,
Yes, I want to create submenus in a context menu. Can you help me here.
Regards,
Hi Frank,
I need the context menu for the application not for datagrid.
In my initial question the phrase "other than stopping right click from javascript" means
"catch the right click in html, call a javascript function and over js call a as function."
The project that you have specified does the above procedure. I don't want to use this
procedure. Is there any other way for achieving submenus in a flex context menu. Could you
please tell me if so..
Regards,
Arvind
Yes, there is.
I don't know, what you exactly mean with this:
other than stopping right click from
javascript.
But, if you want to create a entry in submenu, do this:
//Instance of my own class
private var myContext:myContextMenu = new myContextMenu();
application.contextMenu = myContext.myContextMenu;
//Here is the Class:
package com.my.components
{
/* ////////////////////////////////////////////
///// My Context Menü /////////////////////
///////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
//to use: //
// private var myContext:MyContextMenu = new MyContextMenu(); //
// init() in creationComplete //
// application.contextMenu = myContext.myContextMenu; //
////////////////////////////////////////////////////////////////////////////// */
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.text.TextField;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuBuiltInItems;
import flash.ui.ContextMenuItem;
public class MyContextMenu extends Sprite
{
public var myContextMenu:ContextMenu;
private var menuLabel:String = String.fromCharCode(169)+" My Company GmbH";
public function MyContextMenu()
{
myContextMenu = new ContextMenu;
removeDefaultItems();
addCustomItems();
myContextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
super();
}
private function removeDefaultItems():void
{
myContextMenu.hideBuiltInItems();
var defaultItems:ContextMenuBuiltInItems = myContextMenu.builtInItems;
defaultItems.print = true;
}
private function addCustomItems():void
{
var item:ContextMenuItem = new ContextMenuItem(menuLabel);
myContextMenu.customItems.push(item);
item.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,menuItemSelectHandler);
}
private function menuSelectHandler(event:ContextMenuEvent):void
{
}
private function menuItemSelectHandler(event:ContextMenuEvent):void
{
navigateToURL(new URLRequest('http://www.my-company.de'));
}
private function createLabel():TextField
{
var txtField:TextField = new TextField();
//txtField.text = textLabel;
txtField.text = "RightClickHere";
return txtField;
}
}
}
Have fun
EDIT:
There is an interesting project here. They catch the right click in html, call a javascript function and over js call a as function.
Unfortunately, the limitation of FP or NativeMenu APi allowed just on level contextmenu. Read here
Frank

Resources