My java Project have 4 fragment.
One of the fragment is a chat room, it will require user to input name in a popup-alertDialog when page is called.
Here is the bug. When I put the chatroom to Tab 4, Tab 3 will wrongly display the alertDialog when it(Tab3) was clicked.
When I put the chatroom to Tab 2, Tab 1 and Tab 3 will also have the same problem.
It is tricky to me, I have no idea where the bug come from.
Here is my chatroom.java
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
v = inflater.inflate(R.layout.tab_match_chatroom, container, false);
add_room = (Button) v.findViewById(R.id.btn_add_room);
room_name = (EditText) v.findViewById(R.id.room_name_edittext);
listView = (ListView) v.findViewById(R.id.listView);
listView.setAdapter(arrayAdapter);
add_room.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Map<String, Object> map = new HashMap<String, Object>();
map.put(room_name.getText().toString(), "");
root.updateChildren(map);
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getActivity().getApplicationContext(), TabInChatRoom.class);
intent.putExtra("room_name", ((TextView) view).getText().toString());
intent.putExtra("user_name", name);
startActivity(intent);
}
});
return v;
}
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, list_of_rooms);
request_user_name();
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Set<String> set = new HashSet<String>();
Iterator i = dataSnapshot.getChildren().iterator();
while (i.hasNext()) {
set.add(((DataSnapshot) i.next()).getKey());
}
list_of_rooms.clear();
list_of_rooms.addAll(set);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void request_user_name() {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Enter name:");
final EditText input_field = new EditText(getActivity());
builder.setView(input_field);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
name = input_field.getText().toString();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
request_user_name();
}
});
builder.show();
}
You are showing the popup when the 4th fragment is created (inside onCreate method)
How is it working?
There are multiple related things triggering the issue.
1- ViewPager has offset page limit and default value is 1 (3 Tabs at once). You can change this value. That means, your viewPager only creates 1 from left side, 1 from right side of your current page. Others will be destroyed and recreated when you select fragment in the range limit.
2- When ViewPager has more fragment than is offsetPageLimit, it will not create further ranged Fragments For example: If you have 4 Fragments, first fragment and the 2nd one will be created at start, 4th one will be created when you selected 3rd or 4th tabs.
3- When you select the 3rd or 4th tabs, you are recreating the 4th fragment and it calls onCreate method and afterwards it calls the request_user_name() eventually. And your popup shows up.
First, you can change the viewPagers offsetPage limit by 4 for convenience.
viewPager.setOffscreenPageLimit(4);
Secondly, you need to call request_user_name() method when the Tab 4 clicked, not the 4th fragment created.
You can use OnPageChangeListener like below:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position == 3){
//that means 4th tab
//show the popup
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
More Info:
Link 1
Link 2
Related
I am making a app where a user should be able to click on a pdf file that is stored on firebase and the file should open without saving it to the device and user should be able to read it now currently when I click on the pdf it gets downloaded to device through web browser i want to give this downloading option after the user has viewed the pdf
this is my code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
menuButton=findViewById(R.id.menuButton);
listView=findViewById(R.id.listview);
uploads=new ArrayList<>();
//create method
viewAllFiles();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
pdfClass pdfupload=uploads.get(i);
Intent intent= new Intent(Intent.ACTION_VIEW);
intent.setType("application/pdf");
intent.setData(Uri.parse(pdfupload.getUrl()));
startActivity(intent);
}
});
menuButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, NavigationActivity.class));
finish();
}
});
}
private void viewAllFiles() {
databaseReference= FirebaseDatabase.getInstance().getReference("Uploads");
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for(DataSnapshot postsnapshot: snapshot.getChildren()){
pdfClass pdfClass=postsnapshot.getValue(com.example.dmcianappversion4.pdfClass.class);
uploads.add(pdfClass);
}
String[] Uploads= new String[uploads.size()];
for(int i=0;i<Uploads.length;i++){
Uploads[i]=uploads.get(i).getName();
}
ArrayAdapter<String> adapter=new ArrayAdapter<String>(getApplicationContext(),
android.R.layout.simple_list_item_1,Uploads){
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view=super.getView(position,convertView,parent);
TextView text =(TextView) view.findViewById(android.R.id.text1);
text.setTextColor(Color.BLACK);
text.setTextSize(22);
return view;
}
};
listView.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
this is the code where i need help after onclick it should display the pdf so what code should i put in the on click listener
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
pdfClass pdfupload=uploads.get(i);
Intent intent= new Intent(Intent.ACTION_VIEW);
intent.setType("application/pdf");
intent.setData(Uri.parse(pdfupload.getUrl()));
startActivity(intent);
}
});
so can someone please help im new to android so i dont know very much about android studio
i tried some of the answers that are there in stackoverflow but i couldnt get them to work
I'm currently building a booking application for laundry's machine. I need to get the item count and if the count is zero it will show the dialog box which told user that there is no data in the system.
The Activity code:
public class DobbySelection2 extends AppCompatActivity {
String local;
private Dialog dialog;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private DobbyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dobby_selection2);
dialog = new Dialog(this);
dialog.setContentView(R.layout.custom_dialog2);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
dialog.getWindow().setBackgroundDrawable(getDrawable(R.drawable.custom_dialogbackground));
}
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
dialog.setCancelable(false); //Optional
dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation; //Setting the animations to dialog
Button Yes = dialog.findViewById(R.id.btn_yes);
Yes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(DobbySelection2.this, MainActivity.class );
dialog.dismiss();
startActivity(intent);
}
});
setUpRecyclerView();
}
private void setUpRecyclerView(){
Intent i = getIntent();
local = i.getStringExtra("PLACE");
if (local == null){
local = "Selangor";
}
CollectionReference dobbyRef = db.collection("locality")
.document(local)
.collection("Dobby");
Query query = dobbyRef.orderBy("name", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Dobby> options = new FirestoreRecyclerOptions.Builder<Dobby>()
.setQuery(query, Dobby.class)
.build();
adapter = new DobbyAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
//recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setLayoutManager(new CustomLinearLayoutManager(this));
recyclerView.setAdapter(adapter);
if(adapter.getItemCount() == 0){
dialog.show();
}
adapter.setOnItemClickListener(new DobbyAdapter.OnItemClickListener() {
#Override
public void onItemClick(DocumentSnapshot documentSnapshot, int position) {
Dobby dobby = documentSnapshot.toObject(Dobby.class);
String id = documentSnapshot.getId();
Toast.makeText(DobbySelection2.this, "ID : " + id, Toast.LENGTH_SHORT).show();
Intent intent = new Intent(DobbySelection2.this, Booking2.class);
intent.putExtra("PLACE", local);
intent.putExtra("ID", id);
startActivity(intent);
}
});
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
}
Adapter code:
public class DobbyAdapter extends FirestoreRecyclerAdapter<Dobby, DobbyAdapter.DobbyHolder>{
private OnItemClickListener listener;
/**
* Create a new RecyclerView adapter that listens to a Firestore Query. See {#link
* FirestoreRecyclerOptions} for configuration options.
*
* #param options
*/
public DobbyAdapter(#NonNull FirestoreRecyclerOptions<Dobby> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull DobbyHolder holder, int position, #NonNull Dobby model) {
holder.textViewName.setText(model.getName());
holder.textViewAddress.setText(model.getAddress());
holder.textViewDistance.setText(model.getDistance());
}
#NonNull
#Override
public DobbyHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.itemdobby, parent, false);
return new DobbyHolder(v);
}
class DobbyHolder extends RecyclerView.ViewHolder{
TextView textViewName;
TextView textViewAddress;
TextView textViewDistance;
public DobbyHolder(#NonNull View itemView) {
super(itemView);
textViewName = itemView.findViewById(R.id.nameDobby);
textViewAddress = itemView.findViewById(R.id.addressDobby);
textViewDistance = itemView.findViewById(R.id.distanceDobby);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
if(position != RecyclerView.NO_POSITION && listener != null){
listener.onItemClick(getSnapshots().getSnapshot(position), position);
}
}
});
}
}
public interface OnItemClickListener {
void onItemClick(DocumentSnapshot documentSnapshot, int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}
}
But the dialog box always pop up indicating that the count is zero even though there is data inside of the recycler view. How can I fix this?
My guess is that the dialog you're talking about comes from here:
if(adapter.getItemCount() == 0){
dialog.show();
}
If so, it makes sense that it shows up as this code runs before any data has been loaded.
Data is loaded from Firestore (and most modern cloud APIs) asynchronously, and this changes the order in which code executes. It's easiest to see this if you set breakpoint on the if line above, on adapter.startListening(); and on the first line inside your onBindViewHolder.
If you now run the code in the debugger, you'll see that it:
First hits the if(adapter.getItemCount() == 0){ line
Then adapter.startListening()`
Then gets to onBindViewHolder
So now it hopefully makes sense why your code always show the dialog: no data has been loaded yet at that point.
The solution for this is always the same: you need to make sure that the code that needs the data runs after the data has been loaded. Since you're using the FirestoreRecyclerAdapter from FirebaseUI, you can do this inside its onDataChanged method that signals that a complete snapshot was loaded (regardless of whether there was any data in that snapshot) and is shown in the documentation on data and error events.
So if you move your if check into a onDataChanged method in your DobbyAdapter, it will get called whenever the adapter has loaded a complete snapshot, and it will show the dialog when there are no items.
I want to delete items on a listView when longpressed. In this code you can add (with edittext) a list item with Button, as you can see below.
I have been unable to write the code for deleting them with a long press. What should I do?
Ideally, a long press will bring up a menu and user can touch and delete the section they want.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
addButton = (Button) findViewById(R.id.addButton);
listView = (ListView) findViewById(R.id.listView);
listItems = new ArrayList<String>();
listItems.add("First Item - added on Activity Create");
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, listItems);
listView.setAdapter(adapter);
addButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
listItems.add(editText.getText().toString());
adapter.notifyDataSetChanged();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int position,
long id) {
Toast.makeText(MainActivity.this, "Clicked", Toast.LENGTH_LONG)
.show();
}
});
}
Try this one :
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long arg3) {
adapter.remove(data[position]);//position of the item you click
adapter.notifyDataSetChanged();
return false;
}
});
You can do it with animation:
listView.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long arg3) {
adapter.remove(data[position]);//position of the item you click
adapter.notifyItemRemoved(position);
return false;
}
});
Use this for listview item delete on long click and it should be display alert dialog when you delete any item from list view
listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
removeItemFromList(position);
return true;
}
private void removeItemFromList(int position) {
final int deletePosition = position;
AlertDialog.Builder alert = new AlertDialog.Builder(
this);
alert.setTitle("Delete");
alert.setMessage("Do you want delete this item?");
alert.setPositiveButton("YES", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TOD O Auto-generated method stub
// main code on after clicking yes
songsList.remove(deletePosition);
songAdapter.notifyDataSetChanged();
songAdapter.notifyDataSetInvalidated();
}
});
alert.setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
});
alert.show();
}
I have created the following AlertDialog. In it, the user selects an item from a range of options stored in an XML file and handled using an Adapter, and then clicks either the positive button or the negative button. Here is the code:
public void OpenDialog() {
AlertDialog.Builder dialog = new AlertDialog.Builder(activity);
dialog.setTitle("Promotion Options");
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(activity.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(com.zlaporta.chessgame.R.layout.promotion, null);
dialog.setView(v);
dialog.setPositiveButton("Choose", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (which == 1) {
System.out.println("ok");
}
}
});
dialog.setNegativeButton("Undo Move", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
dialog.show();
Spinner spinner = (Spinner) v.findViewById(com.zlaporta.chessgame.R.id.promotionSpin);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(activity, com.zlaporta.chessgame.R.array.option,
android.R.layout.simple_spinner_item);
//could be other options here instead of simple_spinner_dropdown_item. Just type simple and see what comes up next time
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Now, I'd like information about the user's selection in the spinner to be passed back to the enclosing Activity after the positive button is clicked. What's the best way to do this?
As you seem to have defined the AlertDialog in a separate class, you cannot directly access methods defined inside the Activity from where it is invoked.
One possible way is to define a public method inside the Activity as follows:
public void doSomething(Object spinnerDataObject){
....
}
and access it this way:
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// call the Activity's method here and send the selected item.
((MainActivity)activity).doSomething(parent.getItemAtPosition(position));
dialog.dismiss();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
This will send the selected Spinner data object to the Activity. Whatever you want to do with that object can be done inside doSomething().
I have an ItemClickListener in a gridview. But my itemclicklistener is not being called. There is no activity on item click of the gridview
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
vi = inflater.inflate(R.layout.home, container, false);
Button startdialog = (Button) vi.findViewById(R.id.btnCreateDialog);
startdialog.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent startdialog = new Intent(getActivity(),
start_dialog.class);
startActivity(startdialog);
}
});
Button iv = (Button) vi.findViewById(R.id.btnMoreDialog);
iv.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu homepopup = new PopupMenu(getActivity(), v);
MenuInflater inflater = homepopup.getMenuInflater();
inflater.inflate(R.menu.moredialog, homepopup.getMenu());
homepopup.show();
}
});
PremiumgridView = (StaggeredGridView) vi
.findViewById(R.id.premiumstaggeredGridView);
new Dialogs().execute(urls);
return vi;
}
private class Dialogs extends AsyncTask<String[], Void, String[]> {
#Override
protected String[] doInBackground(String[]... params) {
return params[0];
}
protected void onPostExecute(String[] result) {
int premiummargin = getResources().getDimensionPixelSize(
R.dimen.margin);
PremiumgridView.setItemMargin(premiummargin);
PremiumgridView.setPadding(premiummargin, 0, premiummargin, 0);
final StaggeredAdapter premiumadapter = new StaggeredAdapter(
vi.getContext(), R.id.photoimageview, result,
R.layout.row_staggered_demo);
PremiumgridView.setAdapter(premiumadapter);
premiumadapter.notifyDataSetChanged();
premiumadapter.onClick(vi);
PremiumgridView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(StaggeredGridView parent, View view,
int position, long id) {
String item = premiumadapter.getItem(position).toString();
Toast.makeText(getActivity(), premiumadapter.getItem(position), Toast.LENGTH_SHORT).show();
// Toast.makeText(getActivity(), "You have chose: "+ item, Toast.LENGTH_LONG).show();
}});
}
#Override
protected void onPreExecute() {
}
}
Anyone please?
Thanks,
Solved the problem by removing the button from the xml. Clickable item cannot have another clickable item inside it. Reference OnItemClickListener Not Triggered on Android GridView
Does it crash? If yes, always provide us with the Stacktrace/Logcat.
As far as I know, it´s impossible to directly change the interface from within any Thread other than the UI-Thread - you could either try Handler or use this.
EDIT: OnPostExecute is actually called on the UI-Thread, so this is not a solution for this problem. (see here)