Add a custom view at the top of views in activity Programatically - android

I want to add a custom view (that contains a layout with button and text view) to every Activity I need my custom view name is NetworkErrorView and I have another class that help me observe network status change!
I want to show my custom view on top of other view in every activity that I bulid my NetworkErrorView like this
private NetworkErrorView networkErrorView=new NetworkErrorView(this).build();
And when network stats is change I want to change visibility from Gone to Visible(onChange is called when my network status changed):
#Override
public void onChange(boolean isConnected) {
networkErrorView.networkErorrDialog(isConnected);
}
My onChange() (method work correctly but i cant see my custom view when I change visibility! Can anyone help me??
NetworkErrorView:
public class NetworkErrorView {
private ViewGroup mRootView;
private Activity mActivity;
private LinearLayoutManager mLayoutManager;
private View view;
private Animation translationIn;
private Button btnNetwork;
private LinearLayout networkContainer;
private boolean networkStatus;
public NetworkErrorView(#NonNull Activity activity) {
this.mRootView = (ViewGroup) activity.findViewById(android.R.id.content);
this.mActivity = activity;
this.mLayoutManager = new LinearLayoutManager(mActivity);
}
public NetworkErrorView build(){
view= Assist.inflater.inflate(R.layout.dialog_network_error,mRootView,false);
//View.inflate(mActivity, R.layout.dialog_network_error, mRootView);
btnNetwork=(Button) view.findViewById(R.id.btn_error_network);
btnNetwork.setOnClickListener(onClickListener);
networkContainer=(LinearLayout) view.findViewById(R.id.layout_error_networkcontainer);
translationIn= AnimationUtils.loadAnimation(mActivity,R.anim.anim_wifi_container_in);
mRootView.addView(view, 1);
return this;
}
public void networkErorrDialog(boolean isConnected){
networkStatus=isConnected;
if(isConnected){
view.setVisibility(View.GONE);
}else {
view.setVisibility(View.VISIBLE);
view.bringToFront();
translationIn= AnimationUtils.loadAnimation(mActivity, R.anim.anim_wifi_container_in);
networkContainer.setAnimation(translationIn);
}
}
View.OnClickListener onClickListener=new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!networkStatus){
mActivity.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
}
};
}
mActivity:
public class mActivity extends AppCompatActivity implements NetworkObserver {
private NetworkErrorView networkErrorView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
FontManager.instance().setTypeface(getWindow().getDecorView());
addView();
NetworkManager.init(this);
//...
}
private void addView(){
//...
networkErrorView=new NetworkErrorView(this).build();
}
#Override
public void onChange(boolean isConnected) {
networkErrorView.networkErorrDialog(isConnected);
}
}

I think the view is being added, but because you are adding the view in the 1th position it is not being shown so try something like this
public NetworkErrorView build(){
view= Assist.inflater.inflate(R.layout.dialog_network_error,mRootView,false);
//View.inflate(mActivity, R.layout.dialog_network_error, mRootView);
btnNetwork=(Button) view.findViewById(R.id.btn_error_network);
btnNetwork.setOnClickListener(onClickListener);
networkContainer=(LinearLayout) view.findViewById(R.id.layout_error_networkcontainer);
translationIn= AnimationUtils.loadAnimation(mActivity,R.anim.anim_wifi_container_in);
mRootView.addView(view, 0); //Change this form 1 to 0
return this;
}

Related

how to change fragment views programmatically from the parent activity

I am having a fragment that contains for example one button, I want to allow the Activity containing the fragment to change this button view like for example color and title or src Image.
What's the best way to do that ?
Update : sorry If I wasn't clear enough but I want the activity to change the whole view as it's likes , like setting the padding, the color or anything.
It will create the view programmatically and the fragment should replace the old view by the new one and change the view's ID so that the fragment code isn't affected. And If i created methods in the fragment that takes these views when should the Main activity call them ? since the activity has to wait for the layout of the fragment to be created.
1. You must get you fragment from your activity
val fragment = supportFragmentManager.findFragmentByTag("tag")
or
val fragment = supportFragmentManager.findFragmentById(R.id.fragment)
2. Create a method that will do what you wants in you fragment and call this method from the activity
fragment.hideButton()
or you can use interface
Try this way according to your requirement
public abstract class BaseFragment extends Fragment {
BaseActivity yourActivity;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
yourActivity = (BaseActivity) context;
}
#Override
public void onDetach() {
yourActivity = null;
super.onDetach();
}
public void refreshview(){}
public void setDada(Data data){}
#override
publicn void onStart(){
yourActivity.setCurrentOpenedFragment(this);
}
}
Create the BaseActivity class
public abstract class BaseActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setCurrentOpenedFragment(BaseFragment currentFragment){}
}
Extends the BaseFragment in your fragment i.e.
public class YourFragment extends BaseFragment{
View view;
Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, container, false);
button = (Button)view.findViewById(R.id.button);
return view;
}
#override
publicn void onStart(){
super.onStart();
//yourActivity.setCurrentOpenedFragment(this);
}
Data data;
#override
public void setDada(Data data){
this.data = data;
}
#Override
public void refreshview() {
button.setcolor(data.getcolor());
}
}
Write the below line of code in your Activity class
public class YourActivity extends BaseActivity{
public static final byte NONE = -1;
public static final byte HOME = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
changeFragment(new YourFragment(), HOME);
initview();
}
public void initview(){
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener(){
if(currentFragmentOnDrawer != null){
Data data = new Data();
data.setColor(getResource().getcolor(R.color.red));
currentFragmentOnDrawer.setDada(data);
currentFragmentOnDrawer.refreshview()
}
});
}
BaseFragment currentFragmentOnDrawer;
#Override
public void setCurrentOpenedFragment(BaseFragment currentFragment) {
super.setCurrentOpenedFragment(currentFragment);
this.currentFragmentOnDrawer = currentFragment;
}
public void changeFragment(Fragment targetFragment, byte state) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(R.id.main_fragment, targetFragment, "" + state);
ft.addToBackStack("" + state);
ft.commit();
}
}
Hope it will help for you

How to set up a custom listener in a custom dialog for android?

I'm currently having trouble setting up my custom listener. I just want to pass a string from my dialog to my fragment (where I set up the dialog). I was trying to follow this tutorial: https://www.youtube.com/watch?v=ARezg1D9Zd0.
At minute 10:38, he sets up the listener.
This only problem is that in this, he uses DialogFragment, but I'm extending dialog and I don't know how to attach the context to the listener.
I've tried to set it up in onAttachedToWindow() and in the dialog constructor but it crashes.
What should I actually do?
I'd also appreciate it if someone could explain what the difference is between:
onAttachedToWindow() vs. onAttach(Context context).
Thanks!
MY CUSTOM DIALOG BOX:
public class NewListDialog extends Dialog implements View.OnClickListener {
private Activity c;
private TextInputLayout textInputLayout;
private TextInputEditText editText;
private LinearLayout dialog_root_view;
private Animation fade_out;
private String list_name;
private NewListDialogListener listener;
NewListDialog(Activity a) {
super(a);
this.c = a;
//ANOTHER ATTEMPT TO ATTACH CONTEXT TO LISTENER
//listener = (NewListDialogListener) a.getApplicationContext();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.new_list_dialog);
MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
textInputLayout = findViewById(R.id.dialog_text_input_layout);
editText = findViewById(R.id.dialog_edit_text);
dialog_root_view = findViewById(R.id.dialog_root);
fade_out = AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);
editText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isTextValid(editText.getText())) {
textInputLayout.setError(null);
return true;
}
return false;
}
});
cancel.setOnClickListener(this);
create.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
//Cancel Button
case R.id.dialog_new_list_cancel_button:
dialog_root_view.startAnimation(fade_out);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dismiss();
}
}, 200);
break;
//Create Button
case R.id.dialog_new_list_create_button:
if (!isTextValid(editText.getText())) {
textInputLayout.setError(c.getString(R.string.dialog_error));
} else {
textInputLayout.setError(null);
//record input string
list_name = editText.getText().toString();
//send information to parent activity
//What to put here?
listener.createListName(list_name);
dismiss();
}
break;
default:
break;
}
}
private boolean isTextValid(#Nullable Editable text) {
return text != null && text.length() > 0;
}
//ATTEMPT TO ATTACH CONTEXT TO LISTENER
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
listener = (NewListDialogListener) c.getBaseContext();
} catch (ClassCastException e) {
throw new ClassCastException(c.getBaseContext().toString() + "must implement ExampleDialogListener");
}
}
public interface NewListDialogListener {
void createListName(String listname);
}
}
In case you define a custom dialog then you can declare a method to allow other components call it or listen events on this dialog. Add this method to you custom dialog.
public void setNewListDialogListener(NewListDialogListener listener){
this.listener = listener;
}
NewListDialog.java
public class NewListDialog extends Dialog implements View.OnClickListener {
private Activity c;
private TextInputLayout textInputLayout;
private TextInputEditText editText;
private LinearLayout dialog_root_view;
private Animation fade_out;
private String list_name;
private NewListDialogListener listener;
NewListDialog(Activity a) {
super(a);
this.c = a;
}
public void setNewListDialogListener(NewListDialogListener listener) {
this.listener = listener;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.new_list_dialog);
MaterialButton cancel = findViewById(R.id.dialog_new_list_cancel_button);
MaterialButton create = findViewById(R.id.dialog_new_list_create_button);
textInputLayout = findViewById(R.id.dialog_text_input_layout);
editText = findViewById(R.id.dialog_edit_text);
dialog_root_view = findViewById(R.id.dialog_root);
fade_out = AnimationUtils.loadAnimation(c, R.anim.fade_out_dialog);
editText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (isTextValid(editText.getText())) {
textInputLayout.setError(null);
return true;
}
return false;
}
});
cancel.setOnClickListener(this);
create.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
//Cancel Button
case R.id.dialog_new_list_cancel_button:
dialog_root_view.startAnimation(fade_out);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
dismiss();
}
}, 200);
break;
//Create Button
case R.id.dialog_new_list_create_button:
if (!isTextValid(editText.getText())) {
textInputLayout.setError(c.getString(R.string.dialog_error));
} else {
textInputLayout.setError(null);
//record input string
list_name = editText.getText().toString();
//send information to parent activity
//What to put here?
if (listener != null) {
listener.createListName(list_name);
}
dismiss();
}
break;
default:
break;
}
}
private boolean isTextValid(#Nullable Editable text) {
return text != null && text.length() > 0;
}
public interface NewListDialogListener {
void createListName(String listname);
}
}
In other components such as an activity which must implements NewListDialogListener.
NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(this);
If you don't want the activity implements NewListDialogListener then you can pass a listener instead.
NewListDialog dialog = new NewListDialog(this);
dialog.setNewListDialogListener(new NewListDialog.NewListDialogListener() {
#Override
public void createListName(String listname) {
// TODO: Your code here
}
});
In android Fragments and Activity has lifecycles. Fragments are hosted inside Activity and get the context of host activity via onattach method.
On the other hand Dialog is extended from Object (God class) without any lifecycle and should be treaded as an object.
If your activity is implementing NewListDialogListener then you can do
listener = (NewListDialogListener) a;
onAttachedToWindow : mean the dialog will be drawn on screen soon
and
getApplicationContext() will give you the context object of the application (one per app) which is surely not related with your listener and hence won't work
Reference :
Android DialogFragment vs Dialog
Difference between getContext() , getApplicationContext() , getBaseContext() and “this”
You can use RxAndroid instead of using listener, in this situation I use RxAndroid to get data from dialogs to activities or fragments.
Just need to create a PublishSubject and get the observed data. on activity or fragment :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PublishSubject<String > objectPublishSubject = PublishSubject.create();
objectPublishSubject.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread())
.subscribe(this::onNext);
CustomDialog customDialog = new CustomDialog(this, objectPublishSubject);
customDialog.show();
}
private void onNext(String data) {
Log.i("DIALOG_DATA", data);
}
and you can create dialog like this :
public class CustomDialog extends Dialog implements View.OnClickListener {
private PublishSubject<String> subject;
public CustomDialog(#NonNull Context context, PublishSubject<String> subject) {
super(context);
this.subject = subject;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_dialog);
findViewById(R.id.button).setOnClickListener(this);
}
#Override
public void onClick(View v) {
subject.onNext("Data");
dismiss();
}

How to reach fragment from dialog that is launched from recyclerView

So basically, I have a dialog where the user inputs data. This dialog is launched from a recyclerView with a custom adapter. I need to call notifyDataSetChanged on the fragment from the dialog after the user clicks "finish".
How do I do this?
Code:
public class FoodListAdapter extends RecyclerView.Adapter<FoodListAdapter.ViewHolder>
implements View.OnClickListener {
//blabla
#Override
public void onClick(View v) {
int position = (int) v.getTag();
String foodItemTitle = mFoodItemList.get(position).getTitle();
FoodEditDietDialog dialog = new FoodEditDietDialog();
dialog.show(fm, mFoodItemList.get(position).getTimeStamp());
}
public class Fragment extends Fragment {
//blabla
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragment = inflater.inflate(R.layout.fragment, container, false);
foodList = databaseHelper.getList("somethingsomething");
recyclerView = Fragment.findViewById(R.id.list);
recyclerView.setHasFixedSize(false);
layoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(layoutManager);
adapter = new FoodListAdapter(fm, foodList);
recyclerView.setAdapter(adapter);
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
}
});
}
You need to do this through your hosting Activity.
public interface DataChangeListener {
void onDataChange();
}
public class YourActivity extends Activity implements DataChangeListener {
private List<DataChangeListener> dataChangeListeners = new ArrayList<>();
#Override
public void onDataChange() {
for(DataChangeListener listener in dataChangeListeners) {
listener.onDataChange();
}
}
public void addDataChangeListener(DataChangeListener listener) {
dataChangeListeners.add(listener);
}
public void removeDataChangeListener(DataChangeListener listener) {
dataChangeListeners.remove(listener);
}
}
public class Fragment extends Fragment implements DataChangeListener {
#Override
public void onAttach(Activity activity) {
if (activity instanceOf YourActivity) {
activity.addDataChangeListener(this)
}
}
#Override
public void onDetach() {
Activity activity = getActivity();
if (activity instanceOf YourActivity) {
activity.removeDataChangeListener(this)
}
}
#Override
public void onDataChange() {
adapter.notifyDataSetChanged();
}
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
Activity activity = getActivity();
if (activity instanceOf DataChangeListener) {
activity.onDataChange();
}
}
});
}
So basically, dialog will call activity, activity will notify fragment, fragment will notify adapters. Alternatively, you can pass your fragment (as DataChangeListener) to your adapter, and to your dialog. And call it from there.

Creating Multiple event callbacks from fragment to the activity

I was able to create a single event callback from a fragment to the activity. However, I have problem with creating two event callbacks from the same fragment.
Basically, I have a button on the fragment1 layout, when click on it, it will execute something in mainactivity, and then, it changes hide the Button at fragment1 layout, and then I need to send a Boolean from the fragment to activity, then initiate fragment2.
How can I implement the 2nd callback interface in the mainacativity.
Here is my code:
at Fragment1:
public class Fragment1 extends Fragment{
private static final String TAG = "Fragment1";
Boolean in1, in2;
Button btn1;
ListenerA mListenerA;
public interface ListenerA{
public void methodA(Boolean in1);
};
ListenerB mListenerB;
public interface ListenerB{
public void methodB(Boolean in2);
};
#Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof ListenerA)
mListenerA = (ListenerA)context;
if(context instanceof ListenerB)
mListenerB = (ListenerB)context;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.fragment1, container, false);
btn1 = (Button) myView.findViewById(R.id.btn1_ID);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListenerA.methodA(true);
}
});
return myView;
}
public void showBtnMethod (Boolean showBtn){
if (showBtn==false) {
btn1.setVisibility(View.INVISIBLE);
mListenerB.methodB(true); //***** problematic line
}
}
}
and the code in the main activity is below. please note that on the first line I was able only to implement one method from the fragment.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA {
private static final String TAG = "MainActivity";
public Fragment1 mFragment1;
public Fragment2 mFragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
mFragment1 = new Fragment1();
transaction1.replace(R.id.content_fragment_ID, mFragment1);
transaction1.commit();
}
}
// this gets called by ListenerA when click on the button
public void methodA(Boolean in){
if (in==true){
Toast.makeText(MainActivity.this, "mMethodA Executed", Toast.LENGTH_SHORT).show();
triggerShowMethod();
}
};
private void triggerShowMethod(){
mFragment1.showBtnMethod(false);
};
// Problematic section is below
public void methodB(Boolean in){
if (in==true){
FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
mFragment2 = new Fragment2();
transaction2.replace(R.id.content_fragment_ID, mFragment2);
transaction2.commit();
Toast.makeText(MainActivity.this, "mMethodB Executed", Toast.LENGTH_LONG).show();
}
};
}
You can simply consolidate both interfaces into one:
public interface Listener{
public void methodA(Boolean in1);
public void methodB(Boolean in2);
};
and in your MainActivity:
public class MainActivity extends AppCompatActivity implements Fragment1.Listener
Your activity doesn't implement ListenerB.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA, Fragment1.ListenerB {
}

A custom function structure for my customView.onclick

I have searched but could not find answer of my question.
This is what I have:
private class BoxView extends View {
private String caption;
private OnClickListener bvClickListener = null
public BoxView(Context context) {
super(context);
this.bvClickListener = new this.OnClickListener(){
public void onClick (View v){
/*v.setCaption("X"); view don't have this method */
}}
}
public void setCaption(String s){
this.caption=s;
invalidate();
}
}
This is what I want to have:
private class BoxView extends View {
private String caption;
private OnClickListener bvClickListener = null
public BoxView(Context context) {
super(context);
this.bvClickListener = new this.OnClickListener(){
public void onClick (BoxView bv){
bv.setCaption("X");
}}
}
public void setCaption(String s){
this.caption=s;
invalidate();
}
}
I may need custom methods for my custom views. And I want to be able to pass my custom view instead of view version of it when onclick is triggered so I can access to it directly.
Updated
And I want to have access to real object not a converted one. So I want to avoid this:
public void onClick (View v){
((BoxView)v).setCaption("X");
}
Call setCaption method as in onClick :
public void onClick (View v){
((BoxView)v).setCaption("X");
}
Try this
class Main extents Activity
{
BoxView boxView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if view is used using layout then
boxView = (BoxView)findViewByID(id);
//else if directly used
boxView = new BoxView(this);
box.setOnClickListener(new onClickListener()
{
#Override
public void onClick(View view) {
boxView.setCaption("X");
boxView.invalidate();
}
});
}
}

Categories

Resources