Removing View from getView - android-layout

I'm trying to hide a button inside getView method of an Adapter. Unfortunately, I can't do it.
private class AppListAdapter extends ArrayAdapter<Info> {
public AppListAdapter(Activity activity, List<Info> apps) {
super(activity, android.R.layout.simple_list_item_1, apps);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// if we weren't given a view, inflate one
if (null == convertView) {
convertView = getLayoutInflater()
.inflate(R.layout.activity_apps, null);
}
btnUninstall = (Button) convertView.findViewById(R.id.uninstallButton);
btnUninstall.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
btnUninstall.setVisibility(View.INVISIBLE);
}
}
);
return convertView;
}
}
Any help shall be appreciated?

Try changing this line
btnUninstall.setVisibility(View.INVISIBLE);
To this
v.setVisibility(View.INVISIBLE);

That's because in the adapter android passes the same view over and over again (recycling), try to set the visibility of the button to visible every time.

I checked the code and it works fine for me.!
Hey quick question though, have you declared your btnUninstall anywhere?
I cannot see it anywhere in the code you have provided, thats all.
Button btnUninstall;

Related

use Onclick in extends PagerAdapter

Hi I’m trying to create a horizontal slide where each horizontal page will have a button that will call a Dialog but onClick is not working in extends Pageradapter can anyone tell me what I’m doing wrong?
I gave the name onClickApprove to onClick that I want you to call Dialog. This Dialog is calling an Activity with a Ratingbar to make an assessment.
Thank you.
public class SliderAdapterUsado extends PagerAdapter {
Context context;
LayoutInflater layoutInflater;
BottomSheetDialog dialog;
Button show;
public SliderAdapterUsado(Context context){
this.context = context;
}
public String[] slide_rota ={
"Titulo1",
"Titulo2"
};
public String[] slide_nome={
"Descrção do titulo 1",
"Descrção do titulo 2"
};
#Override
public int getCount(){
return slide_rota.length;
}
#Override
public boolean isViewFromObject(View view, Object object){
return view == (LinearLayout) object;
}
#Override
public Object instantiateItem(ViewGroup container, int position){
layoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.slide_layout_usados, container, false);
TextView slideHeading = view.findViewById(R.id.slide_rota);
TextView slideDescricao = view.findViewById(R.id.slide_nome);
slideHeading.setText(slide_rota[position]);
slideDescricao.setText(slide_nome[position]);
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object){
container.removeView((LinearLayout)object);
}
public void onClickAvaliar(View view) {
show = view.findViewById(R.id.show);
dialog = new BottomSheetDialog(dialog.getContext());
show.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createDialog();
dialog.show();
}
});
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
private void createDialog(){
View view = layoutInflater.inflate(R.layout.activity_rating, null, false);
Button FeedBack = view.findViewById(R.id.FeedBack);
FeedBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.setContentView(view);
}
}
Please read the documentation.
Note this in particular (emphasis mine):
To define the click event handler for a button, add the android:onClick attribute to the element in your XML layout. The value for this attribute must be the name of the method you want to call in response to a click event. The Activity hosting the layout must then implement the corresponding method.
The expectation is that the value set on the onClick xml attribute will be a method on the hosting Activity. Yours is in the adapter. That's why it doesn't work.
So either move that method to the hosting activity, or just handle the click event explicitly:
...
TextView slideHeading = view.findViewById(R.id.slide_rota);
TextView slideDescricao = view.findViewById(R.id.slide_nome);
Button slideButton = view.findViewById(R.id.slide_button);
slideButton.setOnClickListener (...)
...

Cannot create dialog inside a fragment

I am trying to create a dialog inside a fragment.when I am trying to press on the button and enter the dialog the app collaspe.
I guess the code is not right can you please help me with that?
Here is my code:
private void openDialog(){
Dialog dialog=new Dialog(getContext());
//AlertDialog.Builder builder=new AlertDialog.Builder(getContext());
LayoutInflater layoutInflater=this.getLayoutInflater();
View custom_dialog=getActivity().getLayoutInflater().inflate(R.layout.geo_dialog,null);
dialog.setContentView(custom_dialog);
// add_geofence_radius= custom_dialog.findViewById(R.id.radius_size);
save_btn=custom_dialog.findViewById(R.id.save_btn);
cancel_btn=custom_dialog.findViewById(R.id.cancel_btn);
/* save_btn.setOnClickListener(new View.OnClickListener() {
#Override
}
});
*/
/*cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.cancel();
}
});
*/
// dialog.setTitle("hello");
dialog.show();
}
The best way to show dialog in android is to use "DialogFragments" since they are aware of the lifecycle of the view it is attached on (ie. fragments/activities).
Here is an examples provided in Android docs:
public class PurchaseConfirmationDialogFragment extends DialogFragment {
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
return new AlertDialog.Builder(requireContext())
.setMessage(getString(R.string.order_confirmation))
.setPositiveButton(getString(R.string.ok), (dialog, which) -> {} )
.create();
}
public static String TAG = "PurchaseConfirmationDialog";
}
To show the dialog use:
new PurchaseConfirmationDialogFragment().show(
getChildFragmentManager(), PurchaseConfirmationDialog.TAG);
For more reference on dialogFragments, checkout : Create a DialogFragment

Cannot close a custom AlertDialog

so I have an app with three different buttons(parent buttons) on pressing any of them, the custom alert dialog with 9 different buttons is displayed but the functions of these 9 buttons within the alert dialog are different depending on which of the three parent buttons called it. On pressing any of the 9 buttons, I want the app to perform a particular function and then close the alertdialog. Now the problem is that I can easily call the alert dialog by calling the method showcustomdialog(); that I created but I can't dismiss it using alertdialog.dismiss(); inside the OnClickListener of the parent button since the method has a void result type. I've tried using if-else statements but it doesn't work. How can I achieve what is required?
The method:
private void showCustomDialog() {
ViewGroup viewGroup = findViewById(android.R.id.content);
View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_main2, viewGroup, false);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialogView);
final AlertDialog alertDialog = builder.create();
alertDialog.show();
}
I am calling the meathod and using it as follows:
parentbutton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showCustomDialog();
alertbutton1.getId();
alertbutton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
textView1.setText("500");
function();
//I want to dismiss the alertdialog here.
}
});
alertbutton2.getId();
alertbutton2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
textView1.setText("1000");
function();
//I want to dismiss the alertdialog here.
}
});
and so on.
I figured out a solution for you using AlertDialog.
parentbutton1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
createDialog();
}
});
Then the method MUST be a private or public AlertDialog:
private AlertDialog createDialog() {
LayoutInflater inflater = (getActivity()).getLayoutInflater(); // for fragment or getLayoutInflater(); for activity
View v = inflater.inflate(R.layout.dialog_add_new_list, null);
Button okButton = v.findViewById(R.id.confirm_button);
Button cancelButton = v.findViewById(R.id.cancel_button);
final AlertDialog dialog = new AlertDialog.Builder(getActivity()) // for fragment or AlertDialog.Builder ( this ) for activity
.setView(v)
.show();
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View p1) {
dialog.dismiss();
}
});
return dialog;
}
P.S. Replace the ids I used to create this sample with yours.

I want make my botton animate on fragment but i get an error in the load animation

I want ass my application screen comes on my bottons to animate from button to place i know how to do it in an activity but in a fragment it having issues.
There is an error in the this that says this cannot be applied to fragment and when i put get context it does not animate. Please tell me what wrong.
This is my main fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.fragment_main, container, false);
samabtn=(Button) view.findViewById(R.id.samabtn);
samabtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity=(MainActivity)getActivity();
mainActivity.loadParrablesFragment();
}
});
Lovebtn=(Button) view.findViewById(R.id.Lovebtn);
Lovebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity=(MainActivity)getActivity();
mainActivity.loadChapter2Fragment();
}
});
Adventurebtn=(Button) view.findViewById(R.id.Adventurebtn);
Adventurebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity=(MainActivity)getActivity();
mainActivity.loadAdventureFragmnet();
}
});
menbtn=(Button)view.findViewById(R.id.menbtn);
frombottom= AnimationUtils.loadAnimation(this,R.anim.frombottom);
menbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity=(MainActivity)getActivity();
mainActivity.loadMysteryFragment();
}
});
i have tried get context now the error it gone but the animation i want does not work
I am assuming that the problem you're talking about happens on this line:
frombottom= AnimationUtils.loadAnimation(this,R.anim.frombottom);
Assuming I'm right about that, the problem is that the first argument to loadAnimation() must be a Context. Activities are Contexts, which is why this works when you do it inside an Activity. However, Fragments are not Contexts, so you can't pass this as the first argument.
Within a Fragment, the easiest way to get a Context object is to call getContext(), though there are parts of the lifecycle where this will return null. Inside onCreateView(), though, this is safe.
So write this instead:
frombottom= AnimationUtils.loadAnimation(getContext(), R.anim.frombottom);

How to update ListView from completely unrelated class

I've read through a lot of questions on how to update a ListView. They all pretty much say adapter.notifyDataSetChanged() (if in a seperate thread with runOnUiThread).
My problem starts a bit earlier: How do I even get the Adapter I need or for that matter an Activity to call runOnUiThread?
Here is a very simplified version of my current code:
I have a class for the Data, which can be updated from anywhere at any time. The update method needs to start a new Thread, which is why I can't simply wait for a return value.
class Data {
private static double[] data = new double[7]
public static void update(final Context context) {
new Thread(new Runnable() {
#Override
public void run() {
//do lots of complicated stuff
}
}).start();
}
public double[] getData {
return data;
}
I have an Activity (not the main Activity) that, among other stuff, contains the ListView
public class ListViewActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ListView);
ListView listView = (ListView) findViewById(R.id.MyListView);
listView.setAdapter(new CustomListViewAdapter(this));
}
I then use a custom Adapter to set up the ListView how I want it.
class CustomListViewAdapter extends BaseAdapter {
private final LayoutInflater layoutInflater;
public CustomListViewAdapter(Context context) {
layoutInflater = LayoutInflater.from(context);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder viewHolder = new ViewHolder();
if (view == null) {
view = layoutInflater.inflate(R.layout.listView_row_layout, parent, false);
viewHolder.value = (TextView) view.findViewById(R.id.listViewDataTextField);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
double data = Data.getData()[position];
viewHolder.value.setText(data+"");
return view;
}
private class ViewHolder {
TextView value;
}
Now I want to update the ListView with as soon as the Thread in the update() method has finished getting the new data. Getting the data can take several seconds, so it's impossible to predict, what activity will be active by that time. If my ListViewActivity is active, I want the ListView to change to the new data immediately.
So how do I update that ListView, from a different class, which is not an Activity, inside another thread? I don't suppose putting the adapter in a static field is a good idea, since that ListViewActivity is probably created and destroyed all the time? But what other options do I have?
Define a callback interface. Make your update method take an instance of this callback as an argument and call back to it when updating has finished.
public interface UpdateCallback {
public void onUpdateFinished();
}
public void update(final Context context, final UpdateCallback callback) {
new Thread(new Runnable() {
#Override
public void run() {
// do lots of complicated stuff
callback.onUpdateFinished();
}
}).start();
}
Then in your Activity you can notify that the adapter data has changed:
Data.update(this, new UpdateCallback() {
public void onUpdateFinished() {
adapter.notifyDatasetChanged();
}
});
extendIt looks like your major problem can be formulated shortly as "How do I even get the Adapter", so I'll try to address that. Let us try to use an old good Java singleton to solve the problem. The idea is to create a global config and pre-create adapters for all views that you need to update:
public class GlobalConfig {
private static GlobalConfig config = null;
private CustomBaseAdapterOne adapter1 = null;
private CustomBaseAdapterTwo adapter2 = null;
public GlobalConfig getAdapterOne() {return adapter1;}
public GlobalConfig getAdapterTwo() {return adapter2;}
public static synchronized GlobalConfig getInstance() {
if (config == null) {
config = new GlobalConfig();
config.adapter1 = new CustomBaseAdapterOne();
config.adapter2 = new CustomBaseAdapterTwo();
}
return config;
}
}
Your ListViewActivity will need to extend DataSetObserver class and register an observer when it starts. You CustomListAdapter would need to register the observer when it starts and it will also need to be able to get initialized with init params (Context in your case) through a function (e.g. setContext), not through a constructor, so in your ListViewActivity you'll need to do something like below:
GlobalConfig cfg = GlobalConfig.getInstance();
CustomerAdapterOne ad = cfg.getAdapterOne();
ad.setContext(this);
ad.registerDataSetObserver(this);
From a separate thread that needs to update the ListView, you'll run:
GlobalConfig cfg = GlobalConfig.getInstance();
try {
cfg.getAdapterOne().notifyDataSetChanged();
}
catch{... }
I think, it's a good idea to have try/catch here because I don't know what will happen if ListView has already died at the time when you need to notify.
To summarize: you'll need to pre-create one adapter for each view that needs to be updated and make it globally available for everyone who needs it.

Resources