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.
Related
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"
I have an ArrayAdapter which shows some posts using a fragment. In this fragment I have some buttons. So all of the posts shown have these buttons.
The problem is, when I click a button of a post to setText to a field of this post; instead of changing text of post that I clicked, it changes text of newly scrolled item.
For example if I scroll down the ListView a new item comes. Then regardless of which post I clicked it changes text of this new post.
How can I prevent this to happen? I take current post using
getItem(position)
By scroolling I mean new element of the list are loaded and shown.
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.comment_small,parent,false);
TextView tvOwner = (TextView) v.findViewById(R.id.tvCommentSmallOwner);
TextView tvCreationDate = (TextView) v.findViewById(R.id.tvCommentSmallCreationDate);
TextView tvCreationDateValue = (TextView) v.findViewById(R.id.tvCommentSmallCreationDate);
TextView tvContent = (TextView) v.findViewById(R.id.tvCommentSmallContent);
tvVoteCount = (TextView) v.findViewById(R.id.tvCommentVoteCount);
c = getItem(position);
tvOwner.setText(context.getResources().getString(R.string.generic_by) + " " + c.getOwnerId());
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String s =c.getPostDate();
System.out.println(s);
tvCreationDateValue.setText(s);
tvContent.setText(c.getContent());
btnDownVote = (ImageButton) v.findViewById(R.id.btnCommentDownVote);
btnUpVote = (ImageButton) v.findViewById(R.id.btnCommentUpVote);
tvVoteCount.setText("" + c.getNetCount());
btnUpVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
c=getItem(position);
ServerRequests sr = new ServerRequests(getContext());
MemberLocalStore memberLocalStore = new MemberLocalStore(getContext());
Member m = memberLocalStore.getLoggedInMember();
sr.voteComment(c, true, m.getId(), new Consumer<String>() {
#Override
public void accept(String vote) {
tvVoteCount.setText("" + vote);
}
});
}
});
btnDownVote.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
c=getItem(position);
ServerRequests sr = new ServerRequests(getContext());
MemberLocalStore memberLocalStore = new MemberLocalStore(getContext());
Member m = memberLocalStore.getLoggedInMember();
sr.voteComment(c, false, m.getId(), new Consumer<String>() {
#Override
public void accept(String vote) {
tvVoteCount.setText("" + vote);
}
});
}
});
return v;
}
I want to vote (like,dislike) some posts but when I click upvote button that marked as 1, overall vote of the post that marked as 2 changes.
I'm trying to generate a full screen TextView that auto-appends a random binary number to it. I wrote this code:
Button button;
TextView textView;
Random rand;
private static final char[] ALPHA_NUMERIC_STRING = "01".toCharArray();
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,false);
rand = new Random();
textView = (TextView) rootView.findViewById(R.id.textView1);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
for (int i=0; i<1000; i++){
textView.append(String.valueOf(ALPHA_NUMERIC_STRING[rand.nextInt(ALPHA_NUMERIC_STRING.length)]));
}
}
});
button = (Button) rootView.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new CountDownTimer(5000, 1) {
public void onTick(long millisUntilFinished) {
textView.append(String.valueOf(ALPHA_NUMERIC_STRING[rand.nextInt(ALPHA_NUMERIC_STRING.length)]));
final int scrollAmount = textView.getLayout().getLineTop(textView.getLineCount()) - textView.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
if (scrollAmount > 0)
textView.scrollTo(0, scrollAmount);
else
textView.scrollTo(0, 0);
}
public void onFinish() {
textView.append("done!");
}
}.start();
}
});
return rootView;
}
This code works fine. It's writing a random string into my textView. The problem comes when my textView becomes really big. When it has a lot of chars, when I add a new char and try to append it, I notice the add and repaint process is really slow.
Does anybody know why is this being slowed down? How can I make it work fast?
PS: this code is located inside a Fragment.
Use TextView inside a ScrollView to display messages with any no.of lines.
I think this is good for your requirement. Try it once.
<TextView
android:id="#+id/tv"
android:layout_width="fill_parent"
android:layout_height="100px"
android:textColor="#f00"
android:textSize="25px"
android:typeface="serif"
android:textStyle="italic"/>
if you want to change dynamically whenever you want use as below:
TextView textarea = (TextView)findViewById(R.id.tv); // tv is id in XML file for TextView
textarea.setTextSize(20);
I have a ListView dynamically inflated with custom layout that has different text views and a button. On button click, a user specifies options in a dialog window and the data returned to the selected item in the list view.
I expect the data to get inserted in text views of the corresponding item in the list view. However, when the list has fewer item that are not scrollable, no data gets inserted at all when dialog is closed and when it has enough items to be scrollable, the data gets inserted into text views of wrong item in the list. I don't know what I am doing wrong, here is my code:
public double COST_EM = 0.00, COST = 0.00, NUM_CO = 0.00;
private Spinner mPSpinner, mMediSpinner;
private ArrayAdapter<String> pmedi, numCo;
private TextView mPTv, mCoTv, mSubMain, mSubTv;
#Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = null;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.item_custom_layout, parent, false);
// Display image in the ImageView widget
TempP tphoto = tempPList.get(position);
mPTv = (TextView) view.findViewById(R.id.p_tv_po);
mCoTv = (TextView) view.findViewById(R.id.co_tv_po);
mSubMain = (TextView) view.findViewById(R.id.sub_list);
mModify = (Button) view.findViewById(R.id.modify_btn_po);
mModify.setOnClickListener(new View.OnClickListener() {
// calculate the order cost
protected void calculateCost() {
mSub = ((COST_EM + COST) * NUM_CO);
mSubtv.setText("" + Double.toString(mSub));
}
#Override
public void onClick(View v) {
mDialog = new Dialog(PCustom.this);
mDialog.setContentView(R.layout.item_custom_dialog);
mDialog.setTitle("Modify specifications");
mPSpinner = (Spinner) mDialog.findViewById(R.id.ces_sp_dialog);
mSubTv = (TextView) mDialog.findViewById(R.id.sub_der_dialog);
// set spinner adapters (code truncated for brevity)
pmedi = new ArrayAdapter<String>(MyApplication
.getContext(), R.layout.spinner_style, pmedi);
mPSpinner.setAdapter(pmedi);
mPSpinner
.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0,
View arg1, int pos, long arg3) {
if (mPSpinner.getSelectedItem() == "Glossy") {
COST = 2000.00;
} else if (mPSpinner
.getSelectedItem() == "Standard") {
COST = 1500.00;
} else if (mPSpinner
.getSelectedItem() == "Other") {
COST = 1000.00;
}
// calculate the cost
calculateCost();
}
public void onNothingSelected(
AdapterView<?> arg0) {
}
});
Button save = (Button) mDialog
.findViewById(R.id.save_btn_po_dialog);
Button cancel = (Button) mDialog
.findViewById(R.id.cancel_btn_po_dialog);
save.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// String newnumber =
// mobileNumber.getText().toString();
mPTv.setText("" + mPSpinner
.getSelectedItem());
mCoTv.setText((String) mNCoSpinner
.getSelectedItem());
mSubMain.setText(Double.toString(mSub));
mDialog.dismiss();
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDialog.dismiss();
}
});
mDialog.show();
}
});
return view;
}
The method getView() return one item View each time ListView call it with a specific "position" parameter, so the times it is called is no less than the number of items it has. So, your member variables mPTv, mCoTv and mSubMain will be reassigned many times and finally have their values in the final calling of getView().That's why you meet that problem.
To solve your problem, you need to have the correct TextViews when the "save Button" is clicked.Here is how to find those correct TextViews:
In the OnClickListener of mModify Button, the "v" parameter in the method onClick(View v) is the same instance of mModify itself. So, you can use it to find those correct TextViews. Perhaps you can set the item root View as its tag and get the root View in onClick(View v) and then use it to find all those correct TextViews. Here is how to change your code:
mModify = (Button) view.findViewById(R.id.modify_btn_po);
// set the root view as the tag of "modify button".
mModify.setTag(view);
mModify.setOnClickListener(new View.OnClickListener() {
// calculate the order cost
protected void calculateCost() {
mSub = ((COST_EM + COST) * NUM_CO);
mSubtv.setText("" + Double.toString(mSub));
}
#Override
public void onClick(View v) {
// retrieve the root view here, it's the root view of the item on which you
// clicked the "modify button".
View view = (View)v.getTag();
// find the correct TextViews here.
mPTv = (TextView) view.findViewById(R.id.p_tv_po);
mCoTv = (TextView) view.findViewById(R.id.co_tv_po);
mSubMain = (TextView) view.findViewById(R.id.sub_list);
BTW, you didn't optimize your ListView, so it may not scroll smoothly, but this is not what caused your problem.You can refer to this:
How to optimize Android ListView?
Practicing on the ListView, I thought of adding buttons as well to it, rather than showing only content. But in my implementation, the button does not do anything at all.
Plus I was confused whether I could get the position of the button clicked. For now I am just sending the toSend declared inside the OnItemClick in an intent.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
final int toSend = position;
TextView refId = (TextView)view.findViewById(R.id.list_id);
TextView refName = (TextView)view.findViewById(R.id.list_name);
TextView refAdd = (TextView)view.findViewById(R.id.list_address);
Button edit = (Button)view.findViewById(R.id.edit);
edit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
Intent i = new Intent(ListActivity.this, EditLayout.class);
i.putExtra("position", toSend);
startActivity(i);
}
});
String sd_id = refId.getText().toString();
String sd_name = refName.getText().toString();
String sd_add = refAdd.getText().toString();
buildAlert(sd_id, sd_name, sd_add);
}
});
You're pretty close. The "inside" setOnClickListener needs to happen when you create the list row view (the view containing id, name, address, edit).
You can do that during getView(). But where to send the clicks? Instead of creating a new onClickListener, use "this" (your activity). Put an onClick() handler in the activity.
Then, when you get a click, the onClick method will execute. Next problem: how do you know which row clicked? The easiest way that comes to mind is to give the button a different id for e ach row - use the row index (you might need to start at 1 rather than 0 - be warned).
Finally, given the row id, it's easy to start your "nested" activity.
Hope this helps.
(added later)
I do it like this; you'll need to define a layout for your row view:
class MyActivity extends Activity implements View.OnClickListener
{
public void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView (R.layout.my_page);
ListView list = (ListView)findViewById (android.R.id.list);
MyArrayAdapter adapter = new MyArrayAdapter (this, <your array of data>);
list.setAdapter (adapter);
}
#Override
public void onClick(View v)
{
int buttonId = v.getId();
if (buttonId is within range)
... do what you need to do with the click ...
}
private class MyArrayAdapter extends ArrayAdapter<MyData>
{
private Activity act;
//-----------------------------------------------------------------------------
public MyArrayAdapter (Activity act, MyData array)
{
super (act, R.layout.list_row, array);
this.act = act;
}
//-----------------------------------------------------------------------------
#Override
public View getView (int position, View convertView, ViewGroup parent)
{
ViewGroup rowView = (ViewGroup)convertView;
if (rowView == null)
{
LayoutInflater inflater = act.getLayoutInflater();
rowView = (ViewGroup) inflater.inflate (R.layout.list_row,
parent, false);
}
Button button = (Button)rowView.findViewById (R.id.is_member);
button.setId (position+1); // add one to avoid 0 as an id.
button.setOnClickListener (act);
// set field values here -- not shown
return rowView;
}
}
}