add new item on list view from two fragments - android

I am working on alarm app , and I am beginner in android development.
In my app I have 3 tabs "edit", "alarm" and "add alarm" .I have list view in "alarm" tab , and I want in "add alarm" tab add new item in that list , and show it in alarm with old items .
This is my code.
Alarm class
public class Alarm extends Fragment {
public ArrayList<Times> names = new ArrayList<>();
public Alarm() {
// Required empty public constructor
}
ListView list;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_alarm, container, false);;
list = v.findViewById(R.id.listview);
//this demo items .
names.add(new Times( "03:32" , "AM" , "Mon,Wed" , "-Gym Time"));
names.add(new Times( "07:09" , "AM" , "Wed , Mon" , "-Home Time"));
names.add(new Times( "12:00" , "AM" , "Tuh" , "-Gym Time"));
names.add(new Times( "03:36" , "AM" , "Sun,Tue,Wed" , "-Gym Time"));
names.add(new Times( "05:32" , "AM" , "Wed , Mon" , "-Home Time"));
names.add(new Times( "03:52" , "AM" , "Mon" , "-Gym Time"));
names.add(new Times( "08:42" , "AM" , "Sun,Tue,Wed" , "-Gym Time"));
names.add(new Times( "10:22" , "AM" , "Wed , Mon" , "-Gym Time"));
myAdapter adapter = new myAdapter(getContext(), R.layout.custom_list_alarm , names);
Log.e("hi", "onCreateView: " + getContext() );
list.setAdapter(adapter);
return v;
}
}
and here myAdapter.java
public class myAdapter extends BaseAdapter {
private Context c;
Fragment fr ;
private int res ;
private ArrayList<Times> time;
public myAdapter() {
}
public myAdapter(Context c , int res , ArrayList<Times> time)
{
this.c = c;
this.res = res;
this.time = time;
}
public void addAlarm(Times times)
{
this.time.add(times);
}
#Override
public int getCount() {
return time.size();
}
#Override
public Times getItem(int position) {
return time.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if(v == null)
{
v = LayoutInflater.from(c).inflate(res , null , false);
}
TextView tv_name = v.findViewById(R.id.textView);
TextView tv_name2 = v.findViewById(R.id.textView2);
TextView tv_name3 = v.findViewById(R.id.textView3);
TextView tv_name4 = v.findViewById(R.id.textView4);
Times t = getItem(position);
tv_name.setText(t.getTime());
tv_name3.setText(t.getDay());
tv_name2.setText(t.getDays());
tv_name4.setText(t.getSubject());
return v;
}
}
Add Alarm class
public class Add extends Fragment {
public Add() {
// Required empty public constructor
}
private TimePicker timePicker ;
private TextView tv ;
private Button add ;
private EditText label;
private String format = "";
public String subject = "";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_add, container, false);
tv = (TextView) v.findViewById(R.id.textView5);
timePicker = (TimePicker) v.findViewById(R.id.datePicker1);
label = (EditText) v.findViewById(R.id.subject) ;
add = (Button) v.findViewById(R.id.addAlarm);
Log.e("hi2", "addNewAlarm: " + subject );
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addNewAlarm();
}
});
return v;
}
public void addNewAlarm()
{
subject = label.getText().toString();
int hour = timePicker.getHour();
//int minute = timePicker.getCurrentMinute();
if (hour == 0) {
hour += 12;
format = "AM";
} else if (hour == 12) {
format = "PM";
} else if (hour > 12) {
hour -= 12;
format = "PM";
} else {
format = "AM";
}
Times alarm = new Times(String.valueOf(hour), String.valueOf(format), "Test", String.valueOf(subject));
myAdapter test = new myAdapter();
test.addAlarm(alarm);
//tv.setText(String.valueOf(hour + subject )+ subject ) ;
}
}

You will need to do 2 things. The first one is the one you are directly answering, and the second one is the one you have already been suggested (storing them).
For storing, if you are doing something really simple, you could do so with SharedPreferences. So you store (alarm_1_time, "00:00) (alarm_1_name, "my name") for each alarm. Check this and this. Otherwise you can try more complex methods (maybe 'Room', which I have not tried out, but some fellow user is suggesting).
For adding to the list view, you need to:
Firstly, pass from one fragment to another one: as stated here. You basically need to do it through an activity.
Often you will want one Fragment to communicate with another, for
example to change the content based on a user event. All
Fragment-to-Fragment communication is done through the associated
Activity. Two Fragments should never communicate directly.
Source here
Then, to do so:
step 1. Send the data from the new alarm
In add fragment:
Intent intent = new Intent(getActivity().getBaseContext(), YourActivity.class); // activity that hosts the fragments
intent.putExtra("name", alarm_name);
// you can pass as many as you want (labels, names, times, colours, repeating, active, etc.)
// for example:
// intent.putExtra("time", alarm_time);
getActivity().startActivity(intent);
step 2. Receive the data from the new alarm in the activity
In the activity that hosts the fragments:
Intent intent = getIntent();
String my_alarm_name = intent.getStringExtra("name");
Step 3. now from activity, we send it to the fragment:
Bundle bundle = new Bundle();
bundle.putString("alarm", my_alarm_name);
// do the same for all other info (such as time, repetition, etc.) similarly
// now set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);
Step 4. receive in fragment in Fragment onCreateView method:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext=getArguments().getString("message");
return inflater.inflate(R.layout.fragment, container, false);
}
Here you have an example of this method with all the code. An alternative way is through interfaces, as stated here; here you have a question regarding this.
On second place, add new element to list view in the alarms fragment. Here you have a question with more information regarding this, and here a post with a more detailed explanation.
names.add(new_alarm) // append the new alarm to the list you have
adapter.notifyDataSetChanged(); //notify your custom adapter so that it "refreshes"

Related

I keep getting null pointer exception on my getArguments();

From a list, the user can click and item and a fragment will inflate showing the data for the clicked item, where the user also can edit that data and click save to save the edited data.
But from the screen that contains the list is also an add button if the user wants to create a new object.
When the user clicks on an item from the list, a newInstance(..); is called
and in the Fragments onCreateView(); I initilize all variables for that clicked item in the different views. But that is not working well because I keep getting:
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Bundle.getInt(java.lang.String, int)' on a null object reference
newInstance is called from the RecyclerView Adapter onClick():
public static CreateTrainingFragment newInstance(ItemModel itemModel) {
bundle = new Bundle();
bundle.putInt(SB_DURATION, itemModel.getDuration());
bundle.putInt(SB_DISTANCE, itemModel.getDistance());
CreateTrainingFragment createTrainingFragment = new CreateTrainingFragment();
createTrainingFragment.setArguments(bundle);
return createTrainingFragment;
}
Here I use getArguments(); and feed the arguments into Views:
Would the default 0 variable not automatically be inserted into my sbduration.setProgress(); if the argument dont exist?
private void initArgumentsData() {
sbduration.setProgress(getArguments().getInt(SB_DURATION, 0));
sbDistance.setProgress(getArguments().getInt(SB_DISTANCE, 0));
txtduration.setText(getArguments().getInt(SB_DURATION, 0) + " min");
txtDistance.setText(getArguments().getInt(SB_DISTANCE, 0) + " km");
}
Here is how my Views is created and where I use InitArgumentData();
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.createtraining_layout, container, false);
sbduration = (SeekBar) v.findViewById(R.id.seekbar_time);
sbDistance = (SeekBar) v.findViewById(R.id.seekbar_distance);
txtduration = (TextView) v.findViewById(R.id.time_value);
txtDistance = (TextView) v.findViewById(R.id.distance_value);
sbduration.setMax(100);
sbDistance.setMax(50);
initArgumentsData();
}
From RecyclerView I start a new fragment instance like this:
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ItemModel itemModel = realm.getDefaultInstance().where(ItemModel.class).equalTo("timestamp",list.get(getAdapterPosition()).getTimestamp()).findFirst();
CreateTrainingFragment createTrainingFragment = CreateTrainingFragment.newInstance(itemModel, true);
fragmentManager.beginTransaction().replace(R.id.navdrawer_maincontainer,createTrainingFragment).addToBackStack(null).commit();
}
});
From the add button the Fragment is started like this:
addbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction().replace(R.id.navdrawer_maincontainer,new CreateTrainingFragment()).addToBackStack(null).commit();
}
});
getFragmentManager().beginTransaction().replace(R.id.navdrawer_maincontainer,new CreateTrainingFragment()).addToBackStack(null).commit();
Here, you're using new CreateTrainingFragment(). Hence, you're not getting the bundle since there is no bundle attach to it. You should call the newInstance method first to get the an object of CreateTrainingFragment and then put it on replace.
ItemModel itemModel = realm.getDefaultInstance().where(ItemModel.class).equalTo("timestamp",list.get(getAdapterPosition()).getTimestamp()).findFirst();
CreateTrainingFragment createTrainingFragment = CreateTrainingFragment.newInstance(itemModel, true);
getFragmentManager().beginTransaction().replace(R.id.navdrawer_maincontainer, createTrainingFragment).addToBackStack(null).commit();
How about you just check if the arguments exist?
private void initArgumentsData() {
Bundle args = getArguments();
int duration = 0;
int distance = 0;
if (args != null) {
duration = args.getInt(SB_DURATION, 0);
distance = args.getInt(SB_DISTANCE, 0);
}
sbduration.setProgress(duration);
sbDistance.setProgress(distance);
txtduration.setText(duration + " min");
txtDistance.setText(distance + " km");
}
Even if you did call newInstance on the Fragment, you still would need to provide a new ItemModel to that method.

Populating Custom List with Intent Extras - Android

I am an application, which is basically an empty activity (empty list-view) where in the toolbar there is an Add button, clicking the button takes you to another activity with two edit text fields and a button (to submit the activity, in other words send the intent extras to the first activity). I want to take those input (both are strings) from that activity and display them in the list-view in the first activity.
I have made the toolbar and the button, and placed the custom list-view with its adapter in the first activity, and in the second activity I created the necessary views and along with the intent (for passing the two strings).
The problem is, that in the second activity, when I pass the intent extras to the first activity, a new list-view gets created every time instead of appending the list-view.
Can someone help me append the intent extras rather than creating a new list every time the user adds the two inputs?
This is the onCreate method in the first activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_countries);
ActionBar actionBar = getActionBar();
if(actionBar != null)
actionBar.setDisplayHomeAsUpEnabled(true);
listView = (ListView) findViewById(R.id.listView);
populateList();
}
This is the populateList();
public void populateList(){
Bundle countryData = getIntent().getExtras();
if (countryData == null){
return;
}
String country = countryData.getString("country");
String year = countryData.getString("year");
ArrayAdapter<Country> adapter = new CustomAdapter();
listView.setAdapter(adapter);
countryList.add(new Country(country, year));
}
This is the adapter:
private class CustomAdapter extends ArrayAdapter<Country>{
public CustomAdapter() {
super(MyCountries.this, R.layout.list_item, countryList);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null){
view =getLayoutInflater().inflate(R.layout.list_item, parent, false);
}
Country currentCountry = countryList.get(position);
TextView countryText = (TextView) view.findViewById(R.id.countryName);
countryText.setText(currentCountry.getCountryName());
TextView yearText = (TextView) view.findViewById(R.id.yearOfVisit);
yearText.setText(currentCountry.getYear());
notifyDataSetChanged();
return view;
}
}
And this is the onClick() for submitting the input:
public void onClick(View v) {
String country = addCountry.getText().toString();
String year = addYear.getText().toString();
Intent result = new Intent(this, MyCountries.class);
result.putExtra("country", country);
result.putExtra("year", year);
startActivity(result);
}
Thank you very much.
Any help, or guidance will be greatly appreciated.

How to get tab name

I am using slidingtablayout. There are 5 tabs and i am populating each of them with listview from different json requests. I need to get the name or the id of the tab on clicking on one of the items of the list view
You are going to need to supply us with your current code or implementation - that will give us some direction on how to help you.
But my first guess on your implementation: I am assuming when you say SlidingTabLayout you are referring to the code outlined on android developers: https://developer.android.com/samples/SlidingTabsBasic/src/com.example.android.common/view/SlidingTabLayout.html#l199
If that is the case, you can get the tab name from the view pager when a tab is clicked and registered in the click listener:
private class TabClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
for (int i = 0; i < mTabStrip.getChildCount(); i++) {
if (v == mTabStrip.getChildAt(i)) {
mViewPager.setCurrentItem(i);
//Get tab name from mViewPager - differs based on your implementation
return;
}
}
}
}
Yes is that one outlined in the android developers
Ok, here is the situation
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view=null;
if(position == 0){
view = getActivity().getLayoutInflater().inflate(R.layout.pager_item,container, false);
homeList = (ListView) view.findViewById(R.id.home_list);
queryImp(view, "");
homeJSONAdapter = new JSONAdapter(getActivity(), getActivity().getLayoutInflater());
homeList.setAdapter(homeJSONAdapter);
homeList.setOnItemClickListener(this);
}else{
view = getActivity().getLayoutInflater().inflate(R.layout.other_pager_item,container, false);
otherList = (ListView) view.findViewById(R.id.other_list);
queryImp(view, "other");
otherJSONAdapter = new JSONAdapterOther(getActivity(), getActivity().getLayoutInflater());
otherList.setAdapter(ekonomiaJSONAdapter);
otherList.setOnItemClickListener(this);
}
container.addView(view);
view.findViewById(R.id.item_title);
return view;
}
this is the code that populates the tabs on SlidingTabsBasicFragment and the following is the onclick for the items of the lists
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(position == 0)
{
JSONObject jsonObject = (JSONObject) homeJSONAdapter.getItem(position);
String imageURL = jsonObject.optString("img_url");
String artText = jsonObject.optJSONObject("content").optString("rendered");
String artTitle = jsonObject.optJSONObject("title").optString("rendered");
Intent detailIntent = new Intent(getActivity(), SingleArticle.class);
detailIntent.putExtra("imgURL", imageURL);
detailIntent.putExtra("articleText", artText);
detailIntent.putExtra("articleTitle", artTitle);
startActivity(detailIntent);
}else{
JSONObject jsonObject1 = (JSONObject) otherJSONAdapter.getItem(position);
String imageURL1 = jsonObject1.optString("img_url");
String artText1 = jsonObject1.optJSONObject("content").optString("rendered");
String artTitle1 = jsonObject1.optJSONObject("title").optString("rendered");
y
Intent detailIntent1 = new Intent(getActivity(), SingleArticleOther.class);
detailIntent1.putExtra("imgURL1", imageURL1);
detailIntent1.putExtra("articleText1", artText1);
detailIntent1.putExtra("articleTitle1", artTitle1);
startActivity(detailIntent1);
}
which basically, all it does is click on the item of the list and gets to the full article to read. For some reason it all gets a mess. (when i do a log on the position, it gets the position of the item of the list and not that of the tab) When i try to click on an item of the homeJsonAdapter it goes to the article of the otherJsonAdapter. I dont know why.
So what i want to do is get the name of the tab in which the listview is and based on that name, create the JsonAdapter and get the article

Count DownTimer in fragment

I have a navigation that extends Fragment Activity.
What I want to do
When I open the navigation I want to start the count Down Timer.
Then when I access a fragment from the navigation I want to populate two text views with the values of minutes and seconds from the count Down Timer, and while I am on this fragment the text views to be updated with values from count Down Timer.
How can I provide that?
Many thanks :).
In navigation:
LayoutInflater inflater = getLayoutInflater();
View v = inflater.inflate(R.layout.settings_activity, null);
TextView remainedMinTextView = (TextView) v
.findViewById(R.id.remainedMinTextView);
TextView remainedSecTextView = (TextView) v
.findViewById(R.id.remainedSecTextView);
Utils.startCountDownTimer(10000, remainedMinTextView, remainedSecTextView);
in utils class i create the count down timer
public static void startCountDownTimer(final long milis,
final TextView remainedMinTextView,
final TextView remainedSecTextView) {
CountDownTimer countDownTimer = new CountDownTimer(milis, 1000) {
#Override
public void onTick(long millisUntilFinished) {
remainedMinTextView.setText(""
+ String.format("%d", TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished)));
remainedSecTextView
.setText(""
+ String.format(
"%d",
TimeUnit.MILLISECONDS
.toSeconds(millisUntilFinished)
- TimeUnit.MINUTES
.toSeconds(TimeUnit.MILLISECONDS
.toMinutes(millisUntilFinished))));
}
#Override
public void onFinish() {
}
}.start();
}
In the fragment where I have the two text views
#SuppressLint("InflateParams")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/** Inflating the layout for this fragment **/
View v = inflater.inflate(R.layout.settings_activity, null);
// minutes/seconds passed in app
remainedMinTextView = (TextView) v
.findViewById(R.id.remainedMinTextView);
remainedMinTextView.setTypeface(Utils.TypeFace(getActivity()));
remainedSecTextView = (TextView) v
.findViewById(R.id.remainedSecTextView);
remainedMinTextView.setTypeface(Utils.TypeFace(getActivity()));
}
Ok here when I click on 5 minutes for example (here is where the text views are updated)
textViewTimer5 = (TextView) v.findViewById(R.id.imageViewTimer5);
textViewTimer5.setTypeface(Utils.TypeFace(getActivity()));
textViewTimer5.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Utils.startCountDownTimer(300000, remainedMinTextView, remainedSecTextView);
}
});
If I call the count down from here it works... but what I need is when I open the navigation and start the count down and then I open the the fragment that contains the two text views to be updated with values from count down.

how to pull strings from an array adapted listview for a clicked list item

ok so i have an array adapted listview (the array adapting is done in another class).. i just got the click listener working for the list but now i want set it up so that when i click an item it pulls the strings from the clicked item and piggybacks them on the intent to a new activity.. i figure im supposed to use intent.putextra however im not sure how to pull the correct strings corresponding to the item that i click on.. my code is below.. im simply lost to be honest
//Initialize the ListView
lstTest = (ListView)findViewById(R.id.lstText);
//Initialize the ArrayList
alrts = new ArrayList<Alerts>();
//Initialize the array adapter notice with the listitems.xml layout
arrayAdapter = new AlertsAdapter(this, R.layout.listitems,alrts);
//Set the above adapter as the adapter for the list
lstTest.setAdapter(arrayAdapter);
//Set the click listener for the list
lstTest.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView adapterView, View view, int item, long arg3) {
Intent intent = new Intent(
HomePageActivity.this,
PromotionActivity.class
);
finish();
startActivity(intent);
}
});
my alerts class..
public class Alerts {
public String cityid;
public String promoterid;
public String promoshortcontent;
public String promocontent;
public String promotitle;
public String locationid;
public String cover;
#Override
public String toString() {
return "City: " +cityid+ " Promoter: " +promoterid+ "Short Promotion: " +promoshortcontent+ "Promotion: " +promocontent+ "Title: " +promotitle+ "Location: " +locationid+ "Cover: " +cover+ "$";
}
}
anddddd my alertsadapter class..
public class AlertsAdapter extends ArrayAdapter<Alerts> {
int resource;
String response;
Context context;
//Initialize adapter
public AlertsAdapter(Context context, int resource, List<Alerts> items) {
super(context, resource, items);
this.resource=resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
LinearLayout alertView;
//Get the current alert object
Alerts al = getItem(position);
//Inflate the view
if(convertView==null)
{
alertView = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater vi;
vi = (LayoutInflater)getContext().getSystemService(inflater);
vi.inflate(resource, alertView, true);
}
else
{
alertView = (LinearLayout) convertView;
}
//Get the text boxes from the listitem.xml file
TextView textPromo =(TextView)alertView.findViewById(R.id.txtPromo);
TextView textPromoter =(TextView)alertView.findViewById(R.id.txtPromoter);
TextView textLocation =(TextView)alertView.findViewById(R.id.txtLocation);
//Assign the appropriate data from our alert object above
textPromo.setText(al.promocontent);
textPromoter.setText(al.promoterid);
textLocation.setText(al.locationid);
return alertView;
}
}
You need to use the onItemClick event's parameters
a full more readable param enum with param name is
(AdapterView<?> parent, View view, int pos, long id)
that means you have the pos param that indicated the position in the adapter.
What you have to do is:
jump to pos in the adapter
read out the values from the adapter
use putExtra to signup for the intent
had an epiphany over the weekend about how to fix this problem and i finally found a good work around for my app.. i know it isnt optimal because i hard coded the number 100 into it but for my uses as of now i know i wont ever have that many list items..
i added these 2 bits of code to my alertsadapter class
int startzero = 0;
public static String[][] promomatrix = new String[6][100];
and
promomatrix[0][startzero] = al.cityid;
promomatrix[1][startzero] = al.promoterid;
promomatrix[2][startzero] = al.promocontent;
promomatrix[3][startzero] = al.promotitle;
promomatrix[4][startzero] = al.locationid;
promomatrix[5][startzero] = al.cover;
startzero++;
then went to my homepageactivity class and added this to the click listener
Intent intent = new Intent(
HomePageActivity.this,PromotionActivity.class);
intent.putExtra("listitemcity", AlertsAdapter.promomatrix[0][pos]);
intent.putExtra("listitempromoter", AlertsAdapter.promomatrix[1][pos]);
intent.putExtra("listitemcontent", AlertsAdapter.promomatrix[2][pos]);
intent.putExtra("listitemtitle", AlertsAdapter.promomatrix[3][pos]);
intent.putExtra("listitemlocation", AlertsAdapter.promomatrix[4][pos]);
intent.putExtra("listitemcover", AlertsAdapter.promomatrix[5][pos]);
finish();
startActivity(intent);
and finally went to my promotionactivity (where i was trying to send the strings) and added this
Bundle extras = getIntent().getExtras();
if (extras == null){
return;
}
String listitemcity = extras.getString("listitemcity");
String listitempromoter = extras.getString("listitempromoter");
String listitemcontent = extras.getString("listitemcontent");
String listitemtitle = extras.getString("listitemtitle");
String listitemlocation = extras.getString("listitemlocation");
String listitemcover = extras.getString("listitemcover");
worked like a charm.. i hope this helps someone :)

Categories

Resources