how can to use Persian Calander in RecyclerViewAdapter - android

i using a specific date library(https://github.com/mohamad-amin/PersianMaterialDateTimePicker)
now i want using it in a button in Recycler View.
now my problem is I have to define two options in library codes :
1 - I should refer to the activity.
2 - i need to use getSupport FragmentManager().
but this page has been extends with Recycler View.Adapter and I do not know how to call these two options on this page.
RecyclerViewAdapter page :
PersianCalendar persianCalendar = new PersianCalendar();
DatePickerDialog datePickerDialog = DatePickerDialog.newInstance( StudentList.this ,
persianCalendar.getPersianYear() ,
persianCalendar.getPersianMonth() ,
persianCalendar.getPersianDay());
datePickerDialog.show( getSupportFragmentManager() , "datePickerDialog" );
In these pictures you can easily understand me :
enter image description here
enter image description here
enter image description here

You activity must implements TimePickerDialog.OnTimeSetListener and implement the abstact methode onTimeSet:
public class StudentList extends AppCompatActivity implements TimePickerDialog.OnTimeSetListener {
#Override
public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int second) {
}
}
and inside onClick
DatePickerDialog datePickerDialog = DatePickerDialog.newInstance((((StudentList)view.getContext()), persianCalendar.getPersianYear(),
persianCalendar.getPersianMonth(),
persianCalendar.getPersianDay());
OR :
DatePickerDialog datePickerDialog =DatePickerDialog.newInstance(new DatePickerDialog.OnDateSetListener() {
#Override
public void onDateSet(DatePickerDialog view, int year, int monthOfYear, int dayOfMonth) {
}
}, persianCalendar.getPersianYear(),
persianCalendar.getPersianMonth(),
persianCalendar.getPersianDay());

You could try passing the Activity's context when creating an instance of the adapter:
//Code in your Activity
MyAdapter myAdapter = new MyAdapter(this, ...);
Your adapter:
private Context context;
public MyAdapter(Context context, ...){
this.context = context;
//Rest of the constructor...
}
By doing that, you could just add do this:
datePickerDialog.show(context.getSupportFragmentManager(), "datePickerDialog");

You just need an activity context passed in your constructor. Be sure to call new Adapter(this,...) from activities and new Adapter(getActivity(),...) from fragments.
private Context context;
#Override
public void onClick(View v) {
FragmentManager manager = ((Activity) context).getFragmentManager();
FragmentManager manager = ((AppCompatActivity)context).getSupportFragmentManager();
}
try this

Related

Can you get the tag of a date picker

I am opening different date picker fragments in my android app.
The fragement is opened like this.
DialogFragment datePicker = new DatePickerFragment();
datePicker.show(getSupportFragmentManager(), "MY_TAG");
The I implemented the onDateSet method which has the picked date and a DatePicker object. Now I tried to get the tag from the DatePicker object to check which picker has been shown.
There is a method datePicker.getTag(), but this returns null.
Is there a way to get the tag which has been commited in the show method?
By calling datePicker.getTag(), you are getting the wrong tag; which is the DatePicker tag, not the DatePickerFragment tag.
To see the right tag, just use getTag() inside your custom DatePickerFragment
getTag() inside my Fragement class works fine. But how to I pass the
tag back to my activity where I called show() My Fragement currently
only contains the onCreateDialog method where I return a new
DatePickerDialog instance
You can pass a listener to your DatePickerFragment constructor, and trigger its callback with the Fragment tag whenever you set a date.
public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
interface OnDateAdjustedListener {
void onDateAdjusted(String tag);
}
private OnDateAdjustedListener mOnDateAdjustedListener;
// Constructor with a Listener
public DatePickerFragment(OnDateAdjustedListener onDateAdjustedListener) {
mOnDateAdjustedListener = onDateAdjustedListener;
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// .... Handle onCreateDialog
}
#Override
public void onDateSet(DatePicker datePicker, int year, int month, int dayOfMonth) {
// .... Handle onDateSet
// callback with fragment tag
mOnDateAdjustedListener.onDateAdjusted(getTag());
}
}
And in your activity modify the constructor, and implement the interface
public class MainActivity extends AppCompatActivity implements View.OnClickListener, DatePickerFragment.OnDateAdjustedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatePickerFragment dateFragment = new DatePickerFragment(this);
}
#Override
public void onDateAdjusted(String tag) {
Toast.makeText(this, tag, Toast.LENGTH_SHORT).show();
}
}

Update RecyclerView from Dialog

how to update recyclerview from a dialog which is in another class?
My dialog is as a separate class which is called from mainActivity. When I do changes in database, I would like to update recyclerview, which is on mainActivity.
Dialog:
public class Dialog {
DatabaseExecutor databaseExecutor = new DatabaseExecutor();
private final Activity activity;
private final List<Passenger> passengers;
private final int position;
public Dialog (final Activity activity, final List<Passenger> passengers, final int position){
this.activity = activity;
this.passengers = passengers;
this.position = position;
}
public void showDialog (){
final BottomSheetDialog dialog = new BottomSheetDialog(activity);
dialog.setContentView(R.layout.custom_dialog);
final AppCompatImageView dial, message, info, paid, edit, delete;
final AppCompatTextView name;
name = dialog.findViewById(R.id.dialog_name);
paid = dialog.findViewById(R.id.dialog_paid);
name.setText(passengers.get(position).getName());
if(passengers.get(position).isPaid())
paid.setImageResource(R.drawable.money_paid_72);
else
paid.setImageResource(R.drawable.money_unpaid_72);
paid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Passenger passenger = passengers.get(position);
if (!passengers.get(position).isPaid()){
passenger.setPaid(true);
passenger.setTumblr(R.drawable.money_paid);
passenger.setUser(R.drawable.user_icon);
paid.setImageResource(R.drawable.money_paid_72);
}
else {
passenger.setPaid(false);
passenger.setTumblr(R.drawable.money_unpaid);
passenger.setUser(R.drawable.user_icon_unpaid);
paid.setImageResource(R.drawable.money_unpaid_72);
}
databaseExecutor.updatePassenger(activity, passenger);
}
});
dialog.show();
}
}
P.s. when this dialog was in mainActivity, I just called populateData method and it worked. But how to refresh it from this Dialog class?
You can use callback with dialog in MainActivity,
public interface DialogCallback {
public void onDialogCallback();
}
Your Dialog constructor should be,
DialogCallback callback;
public Dialog (final Activity activity, final List<Passenger> passengers, final int position, DialogCallback callback){
this.activity = activity;
this.passengers = passengers;
this.position = position;
this.callback = callback;
}
In your Dialog button click use below code,
paid.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Passenger passenger = passengers.get(position);
if (!passengers.get(position).isPaid()){
passenger.setPaid(true);
passenger.setTumblr(R.drawable.money_paid);
passenger.setUser(R.drawable.user_icon);
paid.setImageResource(R.drawable.money_paid_72);
}
else {
passenger.setPaid(false);
passenger.setTumblr(R.drawable.money_unpaid);
passenger.setUser(R.drawable.user_icon_unpaid);
paid.setImageResource(R.drawable.money_unpaid_72);
}
databaseExecutor.updatePassenger(activity, passenger);
callback.onDialogCallback(); // Add this line
}
});
In your MainActivity use below code,
Dialog dialog = new Dialog(this, passengers, position, new DialogCallback() {
#Override
public void onDialogCallback() {
// Update recycler view code here
}
});
dialog.showDialog();
In Dialog :
Have an interface
public interface onDialogFinishCallback
{
void refreshRecyclerView();
}
Now implement the above in your activity.
before dismiss the dialog or after the db change operation call
callback.refreshRecyclerView
A direct solution would be to call method on activity you passed to the dialog. There refresh data of recyclerview and notifyDataSetChanged() or appropriate.
A more general and imo better, architecture-related solution is to use Room or similar db, where you can observe data for changes. Let's say data in the db is changed anywhere. All the places where this data is observed (like with LiveData), data is refreshed. If you also use Paging library, data is refreshed and animated in recyclerview too.
Dialog shouldn't refresh RecyclverView directly. Instead you should pass listener from activity. Activity can refresh recycler if needed with notifyDataSetChanged.
Usually dialog should be 'dumb' ui and you shouldn't give it too much control, especially not over elements that are not shown inside dialog. Such approach will make your dialogs more reusable and easy to maintain.
Write an interface in your dialog
public interface onClickInterface{
public void updateRecyclerView(int position);
}
declare new variable for this interface in your dialog class
private onClickInterface mOnClickInterface;
then call method updateRecyclerView() from dialog class where you want to update recyclerview
mOnClickInterface.updateRecyclerView(position);
then implement your MainActivity for this interface and override this method
#override
public void updateRecyclerView(int position){
//alter your list which you are passing to your adapter
Passenger passenger = passengers.get(position);
passenger.setPaid(true);
rAdapter.notifyDatasetChanged();
}

Handle data between different fragments using ViewModel and update

I'm trying to implement a datepicker fragment which then has to return the chosen date to the fragment (parent fragment) calling it. I've implemented an interface but it seems that the interface only gets called in the activity, not in the fragment (even if I explicitly call it). I checked this out with log files.
So then I proceeded to use ViewModel class to hold data. Now the problem is, I'm able to store the data in the ViewModel class but I don't know where to call the function of ViewModel in the parent fragment. Calling it on OnCreate/OnCreateView does not help since the fragment has already loaded. Calling it on OnResume/OnAttach crashes the app with null pointer reference.
public class ShareData extends ViewModel{
private int year, month, day;
private String date;
public void getDate(int y, int m, int d)
{
Log.d("Viewmodel is", Integer.toString(year) + " " + Integer.toString(month) + " " + Integer.toString(day));
year = y;
month = m;
day = d;
}
public String setDate()
{
return (Integer.toString(year) + "-" + Integer.toString(month) + "-" + Integer.toString(day));
}
}
This is the code from the DatePicker dialogfragment:
public void onDateSet(DatePicker view, int year, int month, int day) {
viewModel.getDate(year,month+1,day);
datePicked.onDatePicked(view, year, month+1, day);
// Do something with the date chosen by the user
}
And this is my parent fragment:
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.operations_static_new, container, false);
name = view.findViewById(R.id.patient_name);
id = view.findViewById(R.id.patient_id);
date_textview = view.findViewById(R.id.date_static);
date_textview.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
confirmDatePicker(); //this opens fragment to choose date
}
});
model = ViewModelProviders.of(getActivity()).get(ShareData.class);
date_textview.setText(model.setDate());
}
Where do I call date_textview.setText so that the date gets shown on the textview of the date picker?
I don't see any LiveData inside your ViewModel, which tells me you are not using it correctly. What you should do is bind LiveData inside the ViewModel to the fragment you want updated. After that it is trivial to recieve notification of changes in any fragment that is observing the ViewModel.
So to start with your ViewModel should look something like this:
// This will now notify the fragment that is observing of any changes made
public class SharedData extends ViewModel {
private int year, month, day;
private MutableLiveData<String> date = new MutableLiveData<>();
// This will notify observing fragments of changes
public void setDate(int y, int m, int d) {
year = y; month = m; day = d;
date.setValue(year + "-" + month + "-" + day);
}
// This is a factory method for getting the LiveData the fragment will bind to
public LiveData<String> getDate() {
return date;
}
}
Inside the fragment (parent) that updates on date change you do something like this to monitor getDate() from the example above. Which is what is needed for the update to happen after the child or anything else is done updating:
Replace
date_textview.setText(model.setDate());
with
viewModel.getDate().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String newDate) {
// Update your view with the new data
dateTextView.setText(newDate);
}
});
After the setup is done, you can call setDate(y,m,d) from wherever you want, and it will always update the fragments that are observing it.
https://developer.android.com/topic/libraries/architecture/viewmodelhttps://developer.android.com/topic/libraries/architecture/viewmodel

MaterialCalendarView Dotspan not appearing

I'm using this library: https://github.com/prolificinteractive/material-calendarview in my project. Here are segments of my code. I used the EventDecorator class that was provided in the documentation for the Dot Span and renamed it. The calendarView is a MaterialCalendarView in the EventFragment. I wanted to add a Dot Span whenever I click on a specific date in the calendarView, but it doesn't seem to be working/showing up. markedDates is an array list containing all the CalendarDay that were clicked on, so every time I click on a specific date in the calendarView, I add the CalendarDay to the array list. Does anyone know how to fix this/make it work?
public class CurrentDayDecorator implements DayViewDecorator {
private final int color;
private final HashSet<CalendarDay> dates;
public CurrentDayDecorator(int color, Collection<CalendarDay> dates) {
this.color = color;
this.dates = new HashSet<>(dates);
}
#Override
public boolean shouldDecorate(CalendarDay day) {
return dates.contains(day);
}
#Override
public void decorate(DayViewFacade view) {
view.addSpan(new DotSpan(5, color));
}
}
In EventFragment class
calendarView.setOnDateChangedListener(new OnDateSelectedListener() {
#Override
public void onDateSelected(#NonNull MaterialCalendarView widget, #NonNull CalendarDay date, boolean selected) {
markedDates.add(date);
currentDayDecorator = new CurrentDayDecorator(Color.WHITE, markedDates);
widget.addDecorator(currentDayDecorator);
widget.invalidateDecorators();
}
});
I know it's already too late but my solution can be beneficial for a lot more as I myself couldn't find a good implementation of adding dots. I will be showing a simple implementation of putting a red color dot on all those dates where user gonna click and I believe you can customise things accordingly. So, here we go.
First thing first, make a new java class "EventDecorator" and copy all the following code inside that-
public class EventDecorator extends AppCompatActivity implements DayViewDecorator {
private final int color = Color.parseColor("#FF0000");
private final CalendarDay dates;
public EventDecorator(CalendarDay dates) {
this.dates = dates;
}
#Override
public boolean shouldDecorate(CalendarDay day) {
return dates==day;
}
#Override
public void decorate(DayViewFacade view) {
view.addSpan(new DotSpan(5, color));
}
}
Now come to the fragment where we will be setting up the onDateChangegListener, So, copy all this code there inside the createView-
CalendarView calendarView = view.findViewById(R.id.calendarView); //remove view. if it's an activity
calendarView.setOnDateChangedListener(new OnDateSelectedListener() {
#Override
public void onDateSelected(#NonNull MaterialCalendarView widget, #NonNull CalendarDay date, boolean selected) {
EventDecorator eventDecorator= new EventDecorator(date);
widget.addDecorator(eventDecorator);
widget.invalidateDecorators();
}
});
So this is how things are working and if you want to use these dots only on those dates with some events then you can make an array of these dates, store them and then pass them to the EventDecorator class.
Hope this helps someone. Be free to ask anything.

Timepicker with DialogFragment xamarin android

I am opening timepicker in dialogfragment in my fragment class.
var dialog = new TimePickerDialogFragment(_activity, DateTime.Now, new OnTimeSetListener());
dialog.Cancelable = false;
dialog.Show(_fg, null);
Here TimePickerDialogFragment extends DialogFragment.
public class TimePickerDialogFragment : DialogFragment
{
private Activity _activity;
private DateTime _date;
private readonly TimePickerDialog.IOnTimeSetListener _listener;
public TimePickerDialogFragment(Activity activity, DateTime date, TimePickerDialog.IOnTimeSetListener listener)
{
_activity = activity;
_date = date;
_listener = listener;
}
public override Dialog OnCreateDialog(Bundle savedState)
{
var dialog = new TimePickerDialog(_activity, _listener, _date.Hour, _date.Minute, true);
dialog.SetTitle("Enter Time"+ DateTime.Now.ToString());
return dialog;
}
}
Here is my listener class
public class OnTimeSetListener : Java.Lang.Object, TimePickerDialog.IOnTimeSetListener
{
public void OnTimeSet(TimePicker view, int hourOfDay, int minute)
{
}
}
Now I want to update the title as soon as user selects a new time while the pop up is opened. The OnTimeSet is called when I click on set button on popup.I don't want to update there. How can I achieve this?
Is there any other way to open timepicker dialog apart from this that I can try?
I am new to android. Any help is appreciated.
In order to get notified when time is changed you need to create a subclass of TimePickerDialog and override OnTimeChanged method which is called when user changes time in the picker. Add a TimeChanged event in the new subclass and trigger it from the overridden method. In the event handler you will be able to set the dialog title based on the new time.

Categories

Resources