I want to develop the UI in which user will touch the touch pad and if he is registered user of the system , he will be verified by my app. So to indicate that I want to change the fingerprint image by green (valid user) , red (invalid user). So I have created the fragment in which I am getting that result in following two methods
#Override
public void authenticate() {
Log.d(TAG, "authoticate: ");
result = "Yes";
//customBuilder.setImage(R.drawable.ic_fingerprint_pressed);//tried but not working
}
#Override
public void errorAuthenticate() {
Log.d(TAG, "fail: ");
result = "No";
// customBuilder.setImage(R.drawable.ic_fingerprint_pressed_error);//tried but not working
}
Now in same fragment I have created the CustomDialog to show the above images which will be change dynamically. Code for CustomDialog class is given below
public class CustomDialog extends AlertDialog {
public CustomDialog(Context context, int theme) {
super(context, theme);
}
public CustomDialog(Context context) {
super(context);
}
/**
* Helper class for creating a custom dialog
*/
public static class Builder {
private Context context;
private String title;
private int res;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View contentView;
private DialogInterface.OnClickListener
positiveButtonClickListener,
negativeButtonClickListener;
public Builder(Context context) {
this.context = context;
}
public Builder setMessage(String message) {
this.message = message;
return this;
}
public Builder setMessage(int message) {
this.message = (String) context.getText(message);
return this;
}
/**
* Set the Dialog title from resource
* #param title
* #return
*/
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
/**
* Set the Dialog title from String
* #param title
* #return
*/
public Builder setTitle(String title) {
this.title = title;
return this;
}
public Builder setImage(int res){
this.res = res;
return this;
}
/**
* Set a custom content view for the Dialog.
* If a message is set, the contentView is not
* added to the Dialog...
* #param v
* #return
*/
public Builder setContentView(View v) {
this.contentView = v;
return this;
}
/**
* Set the positive button resource and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(int positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = (String) context
.getText(positiveButtonText);
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the positive button text and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(String positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = positiveButtonText;
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the negative button resource and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(int negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = (String) context
.getText(negativeButtonText);
this.negativeButtonClickListener = listener;
return this;
}
/**
* Set the negative button text and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(String negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = negativeButtonText;
this.negativeButtonClickListener = listener;
return this;
}
/**
* Create the custom dialog
*/
public CustomDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// instantiate the dialog with the custom Theme
final CustomDialog dialog = new CustomDialog(context,
R.style.Dialog);
View layout = inflater.inflate(R.layout.capture_finger_touch, null);
// dialog.addContentView(layout, new ViewGroup.LayoutParams(
// ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
// set the dialog title
((ImageView) layout.findViewById(R.id.imgView)).setImageResource(res);
// set the confirm button
if (positiveButtonText != null) {
((Button) layout.findViewById(R.id.btn))
.setText(positiveButtonText);
if (positiveButtonClickListener != null) {
((Button) layout.findViewById(R.id.btn))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
positiveButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_POSITIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.btn).setVisibility(
View.GONE);
}
dialog.setView(layout);
return dialog;
}
}
}
And I have used above CustomDialog by following way
public static String result = "No Found";
CustomDialog.Builder customBuilder = new CustomDialog.Builder(getActivity());
public void captureFingerPrintTouchCustom() {
if (result.equalsIgnoreCase("Yes")) {
customBuilder.setImage(R.drawable.ic_fingerprint_pressed);
} else if (result.equalsIgnoreCase("No")) {
customBuilder.setImage(R.drawable.ic_fingerprint_pressed_error);
//rl.startAnimation(animation);
} else customBuilder.setImage(R.drawable.ic_fingerprint_for_capture);
customBuilder.setPositiveButton("OK2", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog = customBuilder.create();
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
alertDialog.setCanceledOnTouchOutside(false);
alertDialog.setCancelable(false);
alertDialog.show();
}
Here as per the result value I want to change the image of customdialog.
capture_finger_touch.xml code is given below
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/rl"
android:layout_width="#dimen/alert_dialog_size"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#drawable/rounded_white_background"
android:padding="#dimen/view_internal_space">
<ImageView
android:id="#+id/imgView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="#drawable/key_bg_square"
android:src="#drawable/ic_fingerprint_for_capture" />
<Button
android:id="#+id/btn"
style="#style/button_style"
android:layout_height="#dimen/btnHeight"
android:layout_width="wrap_content"
android:layout_below="#+id/imgView"
android:layout_centerHorizontal="true"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:textColor="#color/white"
android:textSize="#dimen/BTC_title_size"
android:textStyle="bold" />
</RelativeLayout>
</RelativeLayout>
But problem is that its not changing the image dynamically. CustomDialog is created like this,
I would suggest you to extend DialogFragment.class, inflate there you layout and communicate with it in you Activity or Fragment
public class FingerprintDialog extends AppCompatDialogFragment implements View.OnClickListener {
private DialogFingerprintBinding binding;
private Listener listener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (Listener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " implement Listener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//if you use databinding
//binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.XXX, null, false);
//binding.buttonCancel.setOnClickListener(this);
View view = inflater.inflate(R.layout.XXX, container, false);
Button button = view.findViewById(R.id.button);
getDialog().setCanceledOnTouchOutside(false);
if (getDialog().getWindow() != null) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
//return binding.getRoot(); for binding
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
listener.cancel();
break;
default:
break;
}
}
public void changeImage(//posible resource) {
//change Image here
}
public interface Listener {
void cancel();
}
}
And then create instance of this dialog nad show it using method DialogFragment#show
You need to setImageResource to ImageView as follows:
private fingerPrintImageView;
public CustomDialog create() {fingerPrintImageView = ((ImageView) layout.findViewById(R.id.imgView)).setImageResource(res);}
public Builder setImage(int res){this.res = res;fingerPrintImageView.setImageResource(res); return this;}
Related
Here,
they is very little to find about adding a Floating Context Menu to RecyclerView items and a lot of different informations. I want one single context menu button and I have implemented it this way:
itemView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
MenuItem delete = menu.add(0, v.getId(), 0, "Delete");
delete.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
int position = getAdapterPosition();
long id = mUploads.get(position).getId();
if (position != RecyclerView.NO_POSITION) {
mListener.onDeleteClick(position, id);
}
return true;
}
});
}
});
This then calls this interface method:
#Override
public void onDeleteClick(int position, long id) {
Toast.makeText(this, "position: " + position + " ID: " + id, Toast.LENGTH_SHORT).show();
}
However, this all looks very messy and I wonder if that approach will lead to problems later.
I use custom dialogs quite often so I use DialogFragment. Note this dialog has an "Ok" and "Cancel" buttons. You can remove the buttons if you do not need them.
You need to create an XML Layout for the Custom DialogFragment "fragment_submit_cancel_dialog". The ability to create your own design gives you a great deal of flexibility in the appearance of your dialog. Here is a simple example, but it can be modified as you need - even add images or lists.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:id="#+id/tvTitle"
android:text="Title"
style="#style/alert_dialog_title"
/>
<TextView
android:id="#+id/tvMessage"
android:text="MyMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_below="#id/tvTitle"
android:layout_centerInParent="true"
android:layout_marginTop="15dp"
/>
</RelativeLayout>
In the Activity you call the DialogFragment you will need to add this:
implements OkCancelDialogFragment.OkCancelDialogListener{
and add the listener method:
#Override
public void onFinishOkCancelDialog(boolean submit) {
if(submit){
// Do what you need here
}
}
Call the DialogFragment like this:
private void startOkDialog(){
String title = "What ever you want as a Title";
String mess = "Your Message!";
OkCancelDialogFragment dialog = OkCancelDialogFragment.newInstance(title, mess);
show(getFragmentManager(), "OkDialogFragment");
}
Now the code for the Custom Dialog Fragment:
public class OkCancelDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
Context context = null;
private String title;
private String message;
private boolean submitData = false;
private OkCancelDialogListener mListener;
public OkCancelDialogFragment() {
}
public static OkCancelDialogFragment newInstance(String title, String message) {
OkCancelDialogFragment fragment = new OkCancelDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
#Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_submit_cancel_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
.setPositiveButton(R.string.button_Ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = true;
//The onDetach will call the Listener! Just in case the user taps the back button
}
})
.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = false;
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (OkCancelDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener.onFinishOkCancelDialog(submitData);
mListener = null;
}
public interface OkCancelDialogListener {
void onFinishOkCancelDialog(boolean submit);
}
}
If you have any questions about how this is implement just let me know.
I have these two adapters OperateClassroomAdapter and EditClassRoom adapter
public class OperateClassroomsAdapter extends RecyclerView.Adapter<OperateClassroomsAdapter.ViewHolder> {
private ArrayList<Classroom> classroomList;
private AdapterClickListener adapterClickListener;
public OperateClassroomsAdapter(ArrayList<Classroom> classroomList) {
this.classroomList = classroomList;
}
/**
* Set on item click listener
* #param adapterClickListener AdapterClickListener
*/
public void setAdapterClickListener(AdapterClickListener adapterClickListener) {
this.adapterClickListener = adapterClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.operate_classroom_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Classroom item = classroomList.get(position);
viewHolder.text.setText(item.getName());
viewHolder.counter.setText(String.valueOf(item.getStudentNumber()));
Log.d("sn",String.valueOf(item.getStudentNumber()));
}
#Override
public int getItemCount()
{
return classroomList == null ? 0 : classroomList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView text;
TextView counter;
public ViewHolder(View itemView)
{
super(itemView);
itemView.setOnClickListener(this);
text = (TextView) itemView.findViewById(R.id.text);
counter = (TextView) itemView.findViewById(R.id.counter);
}
#Override
public void onClick(View v)
{
if (adapterClickListener != null) {
adapterClickListener.OnItemClick(getAdapterPosition());
}
}
}
}
Here in onBindViewHolder Log.d("sn") it shows proper values whereas in the code below
public class EditClassroomsAdapter extends RecyclerView.Adapter<EditClassroomsAdapter.ViewHolder> {
private Context context;
private ArrayList<Classroom> classroomList;
private ListPopupWindow listPopupWindow;
private PopupClickListener popupClickListener;
private AdapterClickListener adapterClickListener;
private DeleteClassBtnClickListener deleteClassBtnClickListener;
private EditClassBtnClickListener editClassBtnClickListener;
private Random mRandom = new Random();
String colorarray[]= new String[]{
"#ffff66",
"#99ff66",
"#ffffff",
"#b3ffff",
"#ff8080",
"#ccdcff",
"#c3c3c3"
};
public EditClassroomsAdapter(Context context, ArrayList<Classroom> classroomList) {
this.context = context;
this.classroomList = classroomList;
listPopupWindow = new ListPopupWindow(context);
}
/**
* Set on item click listener
* #param adapterClickListener AdapterClickListener
*/
public void setAdapterClickListener(AdapterClickListener adapterClickListener) {
this.adapterClickListener = adapterClickListener;
}
/**
* Set on pop-up men item click listener
* #param popupClickListener PopupClickListener
*/
public void setPopupClickListener(PopupClickListener popupClickListener) {
this.popupClickListener = popupClickListener;
}
public void setDeleteClassBtnClickListener(DeleteClassBtnClickListener deleteClassBtnClickListener){
this.deleteClassBtnClickListener=deleteClassBtnClickListener;
}
public void setEditClassBtnClickListener(EditClassBtnClickListener editClassBtnClickListener) {
this.editClassBtnClickListener = editClassBtnClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.edit_classroom_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
Classroom item = classroomList.get(position);
Log.d("sn22",String.valueOf(item.getStudentNumber()));
viewHolder.text.setText(item.getName());
viewHolder.student_count.setText(String.valueOf(item.getStudentNumber()));
viewHolder.settings.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listPopupWindow != null) {
setListPopUpWindow(v, position);
}
}
});
/*
New Delete button added
*/
viewHolder.del_class.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(deleteClassBtnClickListener!=null)
deleteClassBtnClickListener.OnDeleteclassBtnClicked(position);
}
});
/*
edit_class button added
*/
viewHolder.edit_class.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(editClassBtnClickListener!=null)
editClassBtnClickListener.OnEditclassBtnClicked(position);
}
});
Random rand=new Random();
int rgen=rand.nextInt(6)+1;
viewHolder.thumbnail.getLayoutParams().height = getRandomIntInRange(350,200);
viewHolder.thumbnail.setBackgroundColor(Color.parseColor(colorarray[rgen]));
Glide.with(context).load(item.getThumbnail()).into(viewHolder.thumbnail);
// loading album cover using Glide library
// Glide.with(mContext).load(album.getThumbnail()).into(holder.thumbnail);
}
protected int getRandomIntInRange(int max, int min){
return mRandom.nextInt((max-min)+min)+min;
}
#Override
public int getItemCount() {
return classroomList == null ? 0 : classroomList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView text;
ImageButton settings;
ImageView thumbnail;
ImageButton del_class,edit_class;
TextView student_count;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
thumbnail=(ImageView) itemView.findViewById(R.id.cat_image) ;
text = (TextView) itemView.findViewById(R.id.text);
student_count = (TextView) itemView.findViewById(R.id.student_count);
settings = (ImageButton) itemView.findViewById(R.id.settings);
del_class=(ImageButton)itemView.findViewById(R.id.del_class);
edit_class=(ImageButton)itemView.findViewById(R.id.edit_class);
}
#Override
public void onClick(View v) {
if (adapterClickListener != null) {
adapterClickListener.OnItemClick(getAdapterPosition());
}
}
}
/**
* List pop up menu window
* #param anchor View
* #param classroomPosition List item's position
*/
private void setListPopUpWindow(View anchor, final int classroomPosition) {
listPopupWindow.dismiss();
listPopupWindow.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_1,
context.getResources().getStringArray(R.array.edit_classroom)));
listPopupWindow.setAnchorView(anchor);
listPopupWindow.setContentWidth(context.getResources()
.getInteger(R.integer.list_pop_up_width));
listPopupWindow.setDropDownGravity(Gravity.END);
listPopupWindow.setModal(true);
listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int menuItemPosition, long id) {
if (popupClickListener != null) {
popupClickListener.OnPopupClick(classroomPosition, menuItemPosition);
}
listPopupWindow.dismiss();
}
});
listPopupWindow.show();
}
}
The Log.d("sn22") is showing values as 0.Why is this happening ?Or how do i get values from OperateClassroomAdapter here ?
My main point is im passing same arraylist ,still sn22 shows 0 and other shows proper values.Also these are 2 different fragment.
Here is the code for their respective classes where theyre used.
public class EditClassroomFragment extends Fragment {
private Context context;
private static int p=0;
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView list;
private ArrayList<Classroom> arrayList = new ArrayList<>();
private EditClassroomsAdapter adapter;
private RecyclerView.LayoutManager mLayoutManager2 = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
private TextView emptyText; //empty list view text
public EditClassroomFragment() {}
public static EditClassroomFragment newInstance() {
EditClassroomFragment editClassroomFragment = new EditClassroomFragment();
return editClassroomFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.refreshable_list, container, false);
context = rootView.getContext();
list = (RecyclerView) rootView.findViewById(R.id.list);
adapter = new EditClassroomsAdapter(context, arrayList);
list.setAdapter(adapter);
list.setLayoutManager(mLayoutManager2);
list.setHasFixedSize(true);
emptyText = (TextView) rootView.findViewById(R.id.emptyText);
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new SelectClassrooms().execute();
}
});
addDeleteClassBtnClickListener();
addAdapterClickListener();
addPopupClickListener();
addEditClassBtnClickListener();
new SelectClassrooms().execute();
return rootView;
}
/**
* Set empty list text
*/
private void setEmptyText() {
if (emptyText != null) {
if (arrayList.isEmpty()) {
emptyText.setVisibility(View.VISIBLE);
} else {
emptyText.setVisibility(View.GONE);
}
}
}
/**
* Check if the given classroom name already exists
* #param classroomName Selected classroom
* #return
*/
private boolean isAlreadyExist(String classroomName) {
boolean isAlreadyExist = false;
for (Classroom classroom : arrayList) {
if (classroom.getName().equals(classroomName)) {
isAlreadyExist = true;
break;
}
}
return isAlreadyExist;
}
/**
* Add new class item
*/
public void addClassroom() {
final PromptDialog promptDialog = new PromptDialog(context);
promptDialog.setPositiveButton(getString(R.string.ok));
promptDialog.setAllCaps();
promptDialog.setAlphanumeric();
promptDialog.setOnPositiveClickListener(new PromptListener() {
#Override
public void OnPrompt(String promptText) {
closeKeyboard();
promptDialog.dismiss();
if (!TextUtils.isEmpty(promptText)) {
if (!isAlreadyExist(promptText)) {
new InsertClassroom().execute(promptText);
} else {
//alert
CustomAlertDialog customAlertDialog = new CustomAlertDialog(context);
customAlertDialog.setMessage(getString(R.string.couldNotInsertClassroom));
customAlertDialog.setPositiveButtonText(getString(R.string.ok));
customAlertDialog.showDialog();
}
}
}
});
promptDialog.show();
}
public void addClassroom2(String st) {
if(st.equals(null)==false) {
if (!isAlreadyExist(st)) {
new InsertClassroom().execute(st);
} else {
//alert
CustomAlertDialog customAlertDialog = new CustomAlertDialog(context);
customAlertDialog.setMessage(getString(R.string.couldNotInsertClassroom));
customAlertDialog.setPositiveButtonText(getString(R.string.ok));
customAlertDialog.showDialog();
}
}
}
/**
* Change the selected class name
* #param classroomId current classroom to be changed
* #param content current name of the classroom
*/
public void editClassroom(final int classroomId, String content) {
final PromptDialog promptDialog = new PromptDialog(context);
promptDialog.setContent(content);
promptDialog.setPositiveButton(getString(R.string.ok));
promptDialog.setAllCaps();
promptDialog.setAlphanumeric();
promptDialog.setOnPositiveClickListener(new PromptListener() {
#Override
public void OnPrompt(String promptText) {
closeKeyboard();
promptDialog.dismiss();
if (!TextUtils.isEmpty(promptText)) {
new UpdateClassroom().execute(String.valueOf(classroomId), promptText);
}
}
});
promptDialog.show();
}
/**
* Delete classroom
* #param classroom Selected classroom
*/
private void deleteClassroom(final Classroom classroom) {
//show alert before deleting
CustomAlertDialog customAlertDialog = new CustomAlertDialog(context);
customAlertDialog.setMessage(classroom.getName()
+ getString(R.string.sureToDelete));
customAlertDialog.setPositiveButtonText(getString(R.string.delete));
customAlertDialog.setNegativeButtonText(getString(R.string.cancel));
customAlertDialog.setOnClickListener(new OnAlertClick() {
#Override
public void OnPositive() {
new DeleteClassroom().execute(classroom.getId());
}
#Override
public void OnNegative() {
//do nothing
}
});
customAlertDialog.showDialog();
}
/**
* Go inside classroom to add, change or delete students
* #param classroom
*/
private void showStudents(Classroom classroom) {
Intent intent = new Intent(context, EditStudentActivity.class);
intent.putExtra("classroom", classroom);
startActivity(intent);
getActivity().overridePendingTransition(R.anim.move_in_from_bottom,
R.anim.stand_still);
}
/**
* List item click event
*/
private void addAdapterClickListener() {
adapter.setAdapterClickListener(new AdapterClickListener() {
#Override
public void OnItemClick(int position) {
if (arrayList != null && arrayList.size() > position) {
showStudents(arrayList.get(position));
Log.d("sn44",String.valueOf(arrayList.get(position).getStudentNumber()));
}
}
});
}
/**
* Pop-up menu item click event
*/
public void addPopupClickListener() {
adapter.setPopupClickListener(new PopupClickListener() {
#Override
public void OnPopupClick(int itemPosition, int menuPosition) {
if (arrayList != null && arrayList.size() > itemPosition) {
Classroom classroom = arrayList.get(itemPosition);
if (menuPosition == ClassroomPopup.CHANGE_NAME.getValue()) {
editClassroom(classroom.getId(), classroom.getName());
} else if (menuPosition == ClassroomPopup.DELETE_CLASSROOM.getValue()) {
deleteClassroom(classroom);
}
}
}
});
}
/*
Edit button and delete button listeners
*/
public void addDeleteClassBtnClickListener()
{
adapter.setDeleteClassBtnClickListener(new DeleteClassBtnClickListener() {
#Override
public void OnDeleteclassBtnClicked(int position) {
if (arrayList != null && arrayList.size() > position) {
Classroom classroom = arrayList.get(position);
deleteClassroom(classroom);
}
}
});
}
public void addEditClassBtnClickListener()
{
adapter.setEditClassBtnClickListener(new EditClassBtnClickListener() {
#Override
public void OnEditclassBtnClicked(int position) {
if (arrayList != null && arrayList.size() > position) {
Classroom classroom = arrayList.get(position);
editClassroom(classroom.getId(), classroom.getName());
}
}
});
}
/**
* Select classrooms from DB
*/
private class SelectClassrooms extends AsyncTask<Void, Void, ArrayList<Classroom>> {
#Override
protected void onPreExecute() {
swipeRefreshLayout.setRefreshing(true);
}
#Override
protected ArrayList<Classroom> doInBackground(Void... params) {
DatabaseManager databaseManager = new DatabaseManager(context);
ArrayList<Classroom> tmpList = databaseManager.selectClassrooms();
return tmpList;
}
#Override
protected void onPostExecute(ArrayList<Classroom> tmpList) {
swipeRefreshLayout.setRefreshing(false);
arrayList.clear();
if (tmpList != null) {
arrayList.addAll(tmpList);
adapter.notifyDataSetChanged();
setEmptyText();
}
}
}
/**
* Insert classroom name into DB
*/
private class InsertClassroom extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
String classroom = params[0];
DatabaseManager databaseManager = new DatabaseManager(context);
boolean isSuccessful = databaseManager.insertClassroom(classroom);
return isSuccessful;
}
#Override
protected void onPostExecute(Boolean isSuccessful) {
if (isSuccessful) {
new SelectClassrooms().execute();
}
}
}
/**
* Update classroom name in the DB
*/
private class UpdateClassroom extends AsyncTask<String, Void, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
String classroomId = params[0];
String newName = params[1];
DatabaseManager databaseManager = new DatabaseManager(context);
boolean isSuccessful = databaseManager.updateClassroomName(classroomId, newName);
return isSuccessful;
}
#Override
protected void onPostExecute(Boolean isSuccessful) {
if (isSuccessful) {
new SelectClassrooms().execute();
}
}
}
/**
* Delete a classroom item from DB
*/
private class DeleteClassroom extends AsyncTask<Integer, Void, Boolean> {
#Override
protected Boolean doInBackground(Integer... params) {
int classroomId = params[0];
DatabaseManager databaseManager = new DatabaseManager(context);
boolean isSuccessful = databaseManager.deleteClassroom(classroomId);
return isSuccessful;
}
#Override
protected void onPostExecute(Boolean isSuccessful) {
if (isSuccessful) {
new SelectClassrooms().execute();
}
}
}
/**
* Closes keyboard for disabling interruption
*/
private void closeKeyboard(){
try {
InputMethodManager imm = (InputMethodManager)
getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
} catch (Exception ignored) {}
}
}
public class AttendancesFragment extends Fragment {
private Context context;
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView list;
private ArrayList<Classroom> arrayList = new ArrayList<>();
private OperateClassroomsAdapter adapter;
private TextView emptyText; //empty list view text
public AttendancesFragment() {}
public static AttendancesFragment newInstance() {
AttendancesFragment attendancesFragment = new AttendancesFragment();
return attendancesFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.refreshable_list, container, false);
context = rootView.getContext();
list = (RecyclerView) rootView.findViewById(R.id.list);
adapter = new OperateClassroomsAdapter(arrayList);
list.setAdapter(adapter);
list.setLayoutManager(new LinearLayoutManager(context));
list.setHasFixedSize(true);
emptyText = (TextView) rootView.findViewById(R.id.emptyText);
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
new SelectClassrooms().execute();
}
});
addAdapterClickListener();
new SelectClassrooms().execute();
return rootView;
}
/**
* Set empty list text
*/
private void setEmptyText() {
if (emptyText != null) {
if (arrayList.isEmpty()) {
emptyText.setVisibility(View.VISIBLE);
} else {
emptyText.setVisibility(View.GONE);
}
}
}
/**
* List item click event
*/
public void addAdapterClickListener() {
adapter.setAdapterClickListener(new AdapterClickListener() {
#Override
public void OnItemClick(int position) {
if (arrayList != null && arrayList.size() > position) {
Intent intent = new Intent(context, TakeAttendanceActivity.class);
intent.putExtra("classroom", arrayList.get(position));
startActivityForResult(intent, 0);
getActivity().overridePendingTransition(R.anim.move_in_from_bottom,
R.anim.stand_still);
}
}
});
}
/**
* Select classrooms from DB
*/
private class SelectClassrooms extends AsyncTask<Void, Void, ArrayList<Classroom>> {
#Override
protected void onPreExecute() {
swipeRefreshLayout.setRefreshing(true);
}
#Override
protected ArrayList<Classroom> doInBackground(Void... params) {
DatabaseManager databaseManager = new DatabaseManager(context);
ArrayList<Classroom> tmpList = databaseManager.selectClassroomsWithStudentNumber();
return tmpList;
}
#Override
protected void onPostExecute(ArrayList<Classroom> tmpList) {
swipeRefreshLayout.setRefreshing(false);
arrayList.clear();
if (tmpList != null) {
arrayList.addAll(tmpList);
adapter.notifyDataSetChanged();
setEmptyText();
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
Snackbar.make(list, getString(R.string.saved), Snackbar.LENGTH_LONG).show();
}
}
}
If your problem is how pass from data from adapter to another, you can use SharedPreferences to save and get data from adapter to another.
Hope this help you
I'm beginner in Android development. I'm using this library for http requests https://github.com/loopj/android-async-http.
And then I render response JSON in GridView it takes very long time. I'm using progress dialog as preloader, but it's removed before listview is rendered. How I can solve this problem? Thank you.
Here is screenshot of this GridView.
Here is implementation of this activity.
public class LikesActivity extends BottomBarActivity //some custom activity {
List<Anticafe> mAnticafes = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_likes);
/*some code*/
Request.post(Constants.POST_SEARCH_API_LINK, params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Gson gson = new GsonBuilder().create();
Request request = gson.fromJson(new String(responseBody), Request.class);
mAnticafes = request.getAnticafes();
renderListView()
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
hideProcessDialog();
}
});
}
private void renderListView() {
GridView likesList = (GridView) findViewById(R.id.likes_list);
AnticafeAdapter anticafeAdapter = new AnticafeAdapter(this, mAnticafes);
anticafeAdapter.setWidth(getWidth());
likesList.setAdapter(anticafeAdapter);
}
}
Here is full implementaion of adapter.
public class AnticafeAdapter extends BaseAdapter{
public static final String TAG = "image-request";
private Context mContext;
private List<Anticafe> mAnticafes = new ArrayList<>();
private Client mClient;
private View mConvertView;
private int mWidth;
public AnticafeAdapter(Context context, List<Anticafe> anticafes) {
mContext = context;
mAnticafes = anticafes;
}
public void setWidth(int mWidth) {
this.mWidth = (int) (mWidth / 4.7);
}
#Override
public int getCount() {
return mAnticafes.size();
}
#Override
public Anticafe getItem(int position) {
return mAnticafes.get(position);
}
#Override
public long getItemId(int position) {
return getItem(position).getId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Anticafe anticafe = getItem(position);
mClient = AnticafeApplication.getInstanse().getClient();
mConvertView = convertView;
final ProgressDialog processDialog = new ProgressDialog(mContext);
processDialog.setMessage("Информация обновляется. Пожалуйста, подождите.");
if(mConvertView == null) {
mConvertView = LayoutInflater.from(mContext).inflate(R.layout.adapter_popular, null);
}
ImageView cover = (ImageView) mConvertView.findViewById(R.id.cover);
CircularImageView logo = (CircularImageView) mConvertView.findViewById(R.id.logo);
final ImageView like = (ImageView) mConvertView.findViewById(R.id.like);
final TextView likesCount = (TextView) mConvertView.findViewById(R.id.likes_count);
TextView name = (TextView) mConvertView.findViewById(R.id.name);
TextView price = (TextView) mConvertView.findViewById(R.id.price);
if(mClient != null) {
final boolean liked = mClient.containsLike(anticafe.getId());
if(liked) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_like));
} else {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
}
} else {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
}
likesCount.setText(String.valueOf(anticafe.getTotalLikes()));
name.setText(anticafe.getName());
price.setText(anticafe.getPrices());
Picasso.with(mContext).load(anticafe.getAttachment().getCover()).networkPolicy(NetworkPolicy.OFFLINE).into(cover);
Picasso.with(mContext).load(anticafe.getAttachment().getLogo()).resize(mWidth, mWidth).into(logo);
likeMechanism(anticafe, processDialog, like, likesCount);
name.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
price.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
logo.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
cover.setOnClickListener(anticafeOpenActivityEvent(anticafe.getId()));
BottomBarActivity activity = (BottomBarActivity) this.mContext;
activity.hideProcessDialog();
return mConvertView;
}
private void likeMechanism(final Anticafe anticafe, final ProgressDialog processDialog, final ImageView like, final TextView likesCount) {
like.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (mClient == null) {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle("Вы не авторизованы")
.setMessage("До тех пор, пока вы не пройдете авторизацию, вы не сможете пользоваться некоторым функционалом нашего приложение. Авторизация займет всего лишь пару минут.")
.setCancelable(false)
.setNegativeButton("Скрыть", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Авторизоваться", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(mContext, AuthActivity.class);
mContext.startActivity(intent);
Activity activity = ((Activity) mContext);
activity.overridePendingTransition(R.anim.slide_in_left, R.anim.slide_in_right);
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
processDialog.show();
RequestParams params = new RequestParams();
params.add("anticafe_id", anticafe.getId() + "");
AuthedRequest.post(Constants.LIKE_API_LINK, params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
processDialog.hide();
Gson gson = new GsonBuilder().create();
try {
LikeResponse response = gson.fromJson(new String(responseBody, Constants.UTF_8), LikeResponse.class);
if (response.getLikeStatus().equals("unliked")) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_unlike));
} else if (response.getLikeStatus().equals("liked")) {
like.setImageDrawable(mContext.getResources().getDrawable(R.drawable.ic_like));
}
likesCount.setText(String.valueOf(response.getTotalLikes()));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
processDialog.hide();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
try {
Log.d("json", "onSuccess: " + new String(responseBody, Constants.UTF_8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
processDialog.hide();
}
}
});
}
}
});
}
private OnClickListener anticafeOpenActivityEvent(final int id) {
return new OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putInt("entity_id", id);
((BottomBarActivity) mContext).openNewActivity(AnticafeActivity.class, bundle);
}
};
}
private static class LikeResponse {
#SerializedName("status")
#Expose
private Integer status;
#SerializedName("error")
#Expose
private Boolean error;
#SerializedName("likeStatus")
#Expose
private String likeStatus;
#SerializedName("totalLikes")
#Expose
private Integer totalLikes;
public LikeResponse(Integer status, Boolean error, String likeStatus, Integer totalLikes) {
this.status = status;
this.error = error;
this.likeStatus = likeStatus;
this.totalLikes = totalLikes;
}
/**
*
* #return
* The status
*/
public Integer getStatus() {
return status;
}
/**
*
* #param status
* The status
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
*
* #return
* The error
*/
public Boolean getError() {
return error;
}
/**
*
* #param error
* The error
*/
public void setError(Boolean error) {
this.error = error;
}
/**
*
* #return
* The likeStatus
*/
public String getLikeStatus() {
return likeStatus;
}
/**
*
* #param likeStatus
* The likeStatus
*/
public void setLikeStatus(String likeStatus) {
this.likeStatus = likeStatus;
}
/**
*
* #return
* The totalLikes
*/
public Integer getTotalLikes() {
return totalLikes;
}
/**
*
* #param totalLikes
* The totalLikes
*/
public void setTotalLikes(Integer totalLikes) {
this.totalLikes = totalLikes;
}
}
}
You dont show any code to say exactly what is you problem.
But any way its better to use a third party library for loading images from web such as picasso:
http://square.github.io/picasso
this library load your images smoothly and mange caches by itself.
UPDATE:
Other option is that you dont use viewHolder design pattern in your getView method in your adapter class.
In your current code you call findViewById method in every cell of your gridView but you must call it only first time.
to resolve this problem you should use viewHolder design pattern.
An exampple of getView method with view Holder :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
/*
* The convertView argument is essentially a "ScrapView" as described is Lucas post
* http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
* It will have a non-null value when ListView is asking you recycle the row layout.
* So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
*/
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
ObjectItem objectItem = data[position];
// assign values if the object is not null
if(objectItem != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.textViewItem.setText(objectItem.itemName);
viewHolder.textViewItem.setTag(objectItem.itemId);
}
return convertView;
}
Example of View holder class (define your view elements in this class) :
static class ViewHolderItem {
TextView textViewItem;
}
for more info see this :
https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
I have a FragmentA. When I click on a button in FragmentA I go to FragmentB. In FragmentB I have a PopupWindow. The PopupWindow have a ViewPager with two pages.
I took help from this code - Emojicon
I have 2 separate classes, View1 and View2, for the views at page 1 and 2 of the ViewPager respectively. Both these classes, View1 and View2, extends a parent class ViewBase.
Here is my problem:
Scenario 1: When I am at FragmentA the memory graph shows 13MB utilization. When I go to FragmentB without showing PopupWindow the memory graph shows 16MB and when I come back to FragmentA it comes down to 13MB. This is good.
Scenario 2: When I am at FragmentA the memory graph shows 13MB utilization. When I go to FragmentB with showing PopupWindow the memory graph shows 20MB and when I come back to FragmentA it doesn't come down to 13MB.
I have tried Eclipse MAT and Heap dump to find out the issue but still no help. I can see in the MAT that FragmentB is still in memory when I come back to FragmentA holding the instances of PopupWindow, View1 and View2. None of them are released. FragmentB should not be in memory.
Please help me out.
Here is my DemoPopupWindow.java
public class DemoPopupWindow extends PopupWindow {
// Views
private TabLayout mTabLayout;
private CustomViewPager mViewPager;
private PagerAdapter mViewPagerAdapter;
private RelativeLayout mLayout;
private View mRootView;
// Variables
private int mGreyColor, mPrimaryColor;
private OnSoftKeyboardOpenCloseListener onSoftKeyboardOpenCloseListener;
private int keyBoardHeight = 0;
private Boolean pendingOpen = false;
private Boolean isOpened = false;
private Context mContext;
ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
mRootView.getWindowVisibleDisplayFrame(r);
int screenHeight = mRootView.getRootView().getHeight();
int heightDifference = screenHeight - (r.bottom);
if (heightDifference > 100) {
keyBoardHeight = heightDifference;
setSize(WindowManager.LayoutParams.MATCH_PARENT, keyBoardHeight);
if (isOpened == false) {
if (onSoftKeyboardOpenCloseListener != null)
onSoftKeyboardOpenCloseListener.onKeyboardOpen(keyBoardHeight);
}
isOpened = true;
if (pendingOpen) {
showAtBottom();
pendingOpen = false;
}
} else {
isOpened = false;
if (onSoftKeyboardOpenCloseListener != null)
onSoftKeyboardOpenCloseListener.onKeyboardClose();
}
}
};
/**
* Constructor
* #param rootView
* #param mContext
*/
public DemoPopupWindow(View rootView, Context mContext){
super(mContext);
this.mContext = mContext;
this.mRootView = rootView;
Resources resources = mContext.getResources();
View customView = createCustomView(resources);
setContentView(customView);
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setSize((int) mContext.getResources().getDimension(R.dimen.keyboard_height), WindowManager.LayoutParams.MATCH_PARENT);
}
/**
* Set keyboard close listener
* #param listener
*/
public void setOnSoftKeyboardOpenCloseListener(OnSoftKeyboardOpenCloseListener listener){
this.onSoftKeyboardOpenCloseListener = listener;
}
/**
* Show PopupWindow
*/
public void showAtBottom(){
showAtLocation(mRootView, Gravity.BOTTOM, 0, 0);
}
/**
* Show PopupWindow at bottom
*/
public void showAtBottomPending(){
if(isKeyBoardOpen())
showAtBottom();
else
pendingOpen = true;
}
/**
* Check whether keyboard is open or not
* #return
*/
public Boolean isKeyBoardOpen(){
return isOpened;
}
/**
* Set soft keyboard size
*/
public void setSizeForSoftKeyboard(){
mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}
/**
* Remove global layout listener
*/
public void removeGlobalListener() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(mGlobalLayoutListener);
} else {
mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
}
}
/**
* Set PopupWindow size
* #param width
* #param height
*/
public void setSize(int width, int height){
keyBoardHeight = height;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, keyBoardHeight);
mLayout.setLayoutParams(params);
setWidth(width);
setHeight(height);
}
/**
* Create PopupWindow View
* #return
*/
private View createCustomView(Resources resources) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.popup, null, false);
mViewPager = (CustomViewPager) view.findViewById(R.id.pager);
mLayout = (RelativeLayout) view.findViewById(R.id.layout);
mViewPagerAdapter = new ViewPagerAdapter(
Arrays.asList(
new View1(mContext, this),
new View2(mContext, this)
)
);
mViewPager.setAdapter(mViewPagerAdapter);
mPrimaryColor = resources.getColor(R.color.color_primary);
mGreyColor = resources.getColor(R.color.grey_color);
mTabLayout = (TabLayout) view.findViewById(R.id.tabs);
mTabLayout.addTab(mTabLayout.newTab());
mTabLayout.addTab(mTabLayout.newTab());
mTabLayout.setupWithViewPager(mViewPager);
return view;
}
/**
* ViewPager Adapter
*/
private static class ViewPagerAdapter extends PagerAdapter {
private List<ViewBase> views;
public ViewPagerAdapter(List<ViewBase> views) {
super();
this.views = views;
}
#Override
public int getCount() {
return views.size();
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View v = views.get(position).mRootView;
((ViewPager)container).addView(v, 0);
return v;
}
#Override
public void destroyItem(ViewGroup container, int position, Object view) {
((ViewPager)container).removeView((View)view);
}
#Override
public boolean isViewFromObject(View view, Object key) {
return key == view;
}
}
/**
* Soft keyboard open close listener
*/
public interface OnSoftKeyboardOpenCloseListener{
void onKeyboardOpen(int keyBoardHeight);
void onKeyboardClose();
}
}
Please note that I haven't pasted complete PopupWindow class here but only the necessary part.
Here is how I am using this DemoPopupWindow in my FragmentB
mPopupWindow = new DemoPopupWindow(mLayout, getActivity());
mPopupWindow.setSizeForSoftKeyboard();
// If the text keyboard closes, also dismiss the PopupWindow
mPopupWindow.setOnSoftKeyboardOpenCloseListener(new DemoPopupWindow.OnSoftKeyboardOpenCloseListener() {
#Override
public void onKeyboardOpen(int keyBoardHeight) {
}
#Override
public void onKeyboardClose() {
if (mPopupWindow.isShowing())
mPopupWindow.dismiss();
}
});
In FragmentB onDestroy I am calling this method to remove GlobalLayoutListener
mPopupWindow.removeGlobalListener();
I have a button in FragmentB to show and dismiss PopupWindow.
Here is my ViewBase.java
public class ViewBase {
public View mRootView;
DemoPopupWindow mPopup;
private Context mContext;
public ViewBase (Context context, DemoPopupWindow popup) {
mContext = context;
mPopup = popup;
}
public ViewBase () {
}
}
Here is my View1
public class View1 extends ViewBase{
// Views
public View mRootView;
DemoPopupWindow mPopup;
private LinearLayout mLayoutText;
// Variables
private Context mContext;
private List<String> mText;
/**
* Constructor
*/
public View1(Context context, DemoPopupWindow popup) {
super(context, popup);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
mPopup = popup;
mRootView = inflater.inflate(R.layout.fragment_view1, null);
mContext = context;
// Set parent class rootview
super.mRootView = mRootView;
registerViews(mRootView);
registerListeners();
populateText();
}
/**
* Register all the views
* #param view
*/
private void registerViews(View view) {
mLayoutText = (LinearLayout) view.findViewById(R.id.view1_layout);
mText = TextManager.getInstance().getText();
}
/**
* Populate text
*/
private void populateText() {
int length = mText.size();
for(int i=0; i<length; i++) {
addNewText(mText.get(i).getText());
}
}
/**
* Add new text
* #param text
*/
private void addNewText(final String text) {
TextView textView = createTextView(text);
mLayoutText.addView(textView);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Do something
}
});
}
/**
* Create textview
* #param text
* #return
*/
private TextView createTextView(final String text) {
TextView textView = new TextView(mContext);
FlowLayout.LayoutParams params = new FlowLayout.LayoutParams(FlowLayout.LayoutParams.WRAP_CONTENT, 40);
params.setMargins(4, 4, 0, 0);
textView.setLayoutParams(params);
textView.setClickable(true);
textView.setGravity(Gravity.CENTER);
textView.setPadding(10, 0, 10, 0);
textView.setText(text);
textView.setTextSize(20);
return textView;
}
}
EDIT AGAIN:
I have found the issue but I dont know how to fix it. The problem is with mGlobalLayoutListener. This is holding the reference of some view. If I don't use GlobalLayoutListener at all then the FragmentB instance is getting removed from the memory.
Even after calling removeGlobalLayout(), this listener is not getting released. Please help me out.
are you sure CustomPopupWindow is causing you memory leak? Have you done garbage collection before running heap dump, maybe there is no leak at all..?
It's called onDestroy in FragmentB with popup when you goes back to fragmentA?
How to remove safely GlobalLayoutListener ?
Caution of your Android version, since api is deprecated! :)
Can you try this
if (Build.VERSION.SDK_INT < 16) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
} else {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
public class CustomDialog extends Dialog {
public int result = -1;
public CustomDialog(Context context, int theme) {
super(context, theme);
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rdbGp1);
radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(RadioGroup arg0, int arg1)
{
result = arg1;
Log.i("Dialog", "Result="+result);
cancel();
}
});
}
public CustomDialog(Context context) {
super(context);
}
/**
* Helper class for creating a custom dialog
*/
public static class Builder {
private Context context;
private String title;
private String message;
private String positiveButtonText;
private String negativeButtonText;
private View contentView;
private DialogInterface.OnClickListener
positiveButtonClickListener,
negativeButtonClickListener;
public Builder(Context context) {
this.context = context;
}
/**
* Set the Dialog message from String
* #param title
* #return
*/
public Builder setMessage(String message) {
this.message = message;
return this;
}
/**
* Set the Dialog message from resource
* #param title
* #return
*/
public Builder setMessage(int message) {
this.message = (String) context.getText(message);
return this;
}
/**
* Set the Dialog title from resource
* #param title
* #return
*/
public Builder setTitle(int title) {
this.title = (String) context.getText(title);
return this;
}
/**
* Set the Dialog title from String
* #param title
* #return
*/
public Builder setTitle(String title) {
this.title = title;
return this;
}
/**
* Set a custom content view for the Dialog.
* If a message is set, the contentView is not
* added to the Dialog...
* #param v
* #return
*/
public Builder setContentView(View v) {
this.contentView = v;
return this;
}
/**
* Set the positive button resource and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(int positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = (String) context
.getText(positiveButtonText);
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the positive button text and it's listener
* #param positiveButtonText
* #param listener
* #return
*/
public Builder setPositiveButton(String positiveButtonText,
DialogInterface.OnClickListener listener) {
this.positiveButtonText = positiveButtonText;
this.positiveButtonClickListener = listener;
return this;
}
/**
* Set the negative button resource and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(int negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = (String) context
.getText(negativeButtonText);
this.negativeButtonClickListener = listener;
return this;
}
/**
* Set the negative button text and it's listener
* #param negativeButtonText
* #param listener
* #return
*/
public Builder setNegativeButton(String negativeButtonText,
DialogInterface.OnClickListener listener) {
this.negativeButtonText = negativeButtonText;
this.negativeButtonClickListener = listener;
return this;
}
/**
* Create the custom dialog
*/
public CustomDialog create() {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// instantiate the dialog with the custom Theme
final CustomDialog dialog = new CustomDialog(context,
R.style.Dialog);
dialog.setOnCancelListener(new OnCancelListener()
{
public void onCancel(DialogInterface arg0)
{
Log.i("FooDialog", "Result="+dialog.result);
}
});
View layout = inflater.inflate(R.layout.credits, null);
dialog.addContentView(layout, new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
// set the dialog title
((TextView) layout.findViewById(R.id.title)).setText(title);
// set the confirm button
if (positiveButtonText != null) {
((Button) layout.findViewById(R.id.positiveButton))
.setText(positiveButtonText);
if (positiveButtonClickListener != null) {
((Button) layout.findViewById(R.id.positiveButton))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
positiveButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_POSITIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.positiveButton).setVisibility(
View.GONE);
}
// set the cancel button
if (negativeButtonText != null) {
((Button) layout.findViewById(R.id.negativeButton))
.setText(negativeButtonText);
if (negativeButtonClickListener != null) {
((Button) layout.findViewById(R.id.negativeButton))
.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
negativeButtonClickListener.onClick(
dialog,
DialogInterface.BUTTON_NEGATIVE);
}
});
}
} else {
// if no confirm button just set the visibility to GONE
layout.findViewById(R.id.negativeButton).setVisibility(
View.GONE);
}
// set the content message
if (contentView != null) {
// if no message set
// add the contentView to the dialog body
((LinearLayout) layout.findViewById(R.id.content))
.removeAllViews();
((LinearLayout) layout.findViewById(R.id.content))
.addView(contentView,
new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
}
dialog.setContentView(layout);
return dialog;
}
}
}
Hello i am building android app and i am trying to return selected RadioButton id from the custom dialog to the main acivity but the app force closes on this line radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener()
Can somebody give some hints thank you
Make sure you imported the good class for that event
android.widget.RadioGroup.OnCheckedChangeListener
and not the Compound Button version.