Hi All I have followed the following example http://www.google.com/codesearch#search/&q=NumberFormattingTextWatcher&exact_package=android&type=cs
I have CurrencyTextWatcher as a seperate class. I need this as I will be applying to several pages.
I can't figure out why, but if I use setContentView(text) it will work as only 1 big text box, then I can't see the rest of my xml .
If I use setContentView(R.layout.main); my xml works properly except for the TextWatcher wont fire for my txta EditText box
Java
public class CalcTestActivity extends Activity {
private EditText txta;
private TextView txtb;
private TextView txtc;
private EditText text;
private double a = 0;
private double b = 0;
private double c = 0;
private Button buttonCalc;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initControls();
text = new EditText(this);
text.addTextChangedListener(new CurrencyTextWatcher());
//setContentView(text);
}
private String FormatValue(double value)
{
NumberFormat nf = NumberFormat.getInstance();
return "$ "+ nf.format(value);
}
private void initControls() {
txta = (EditText)findViewById(R.id.txta);
txtb = (TextView)findViewById(R.id.txtb);
txtc = (TextView)findViewById(R.id.txtc);
buttonCalc = (Button)findViewById(R.id.buttonCalc);
buttonCalc.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {calculate(); }
private void calculate() {
a=Double.parseDouble(txta.getText().toString());
b=Math.round(a*.88);
txtb.setText(FormatValue(b));
c=Math.round((a*.87)-(b*.28));
txtc.setText(FormatValue(c));
}
});
}
}
CurrencyTextWatcher Class
public class CurrencyTextWatcher implements TextWatcher {
boolean mEditing;
public CurrencyTextWatcher() {
mEditing = false;
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
if(!mEditing) {
mEditing = true;
String digits = s.toString().replaceAll("\\D", "");
NumberFormat nf = NumberFormat.getCurrencyInstance();
try{
String formatted = nf.format(Double.parseDouble(digits)/100);
s.replace(0, s.length(), formatted);
} catch (NumberFormatException nfe) {
s.clear();
}
mEditing = false;
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
}
XML
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Number1"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="#+id/txta"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:numeric="integer"/>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Number2"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/txtb"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Your Answer is"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/txtc"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:hint="0" />
<Button
android:id="#+id/buttonCalc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Calculate" />
</LinearLayout>
I took your code. I observed that the code you have shared here is getting all views from xml.
In this case you are calling
text.addTextChangedListener(new CurrencyTextWatcher());
in your onCreate method, wherein text is done using java. You wont get a call back for your onTextChanged, beforeTextChanged or afterTextChanged because all your views are taken from xml. So please after your
initControls();
in onCreate() add below line
txta.addTextChangedListener(new CurrencyTextWatcher());
and comment
text.addTextChangedListener(new CurrencyTextWatcher());
that line is not needed. I have verified its working fine.
if works vote and accept the answer
what the code you have implemented in afterTextChanged implement the same for onTextChanged. It will fire and gives the call back.
Secondly, If there is problem in views check your layout and their params. if it is not proper it wont appear properly in the UI
Related
EditText
<android.support.v7.widget.AppCompatEditText
android:id="#+id/itemEditText_id"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_marginTop="8dp"
android:layout_marginStart="2dp"
android:layout_marginEnd="4dp"
android:lines="2"
android:scrollHorizontally="false"
android:maxLength="69"
android:scrollbars="vertical"
android:background="#drawable/round_border_edit_text"
android:hint="Go ahead \nSend messge"
android:inputType="textMultiLine|textLongMessage"
android:textAppearance="#style/TextAppearance.AppCompat.Body2"
android:maxLines="2"
android:minLines="1"
/>
this is my xml code if something needs to be added or removed here please tell.
java code which i'm using to achieve what i want like whatsapp's editText but its not working quite well
final AppCompatEditText editText = holder.itemEditText;
editText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// if edittext has 10chars & this is not called yet, add new line
if(editText.getText().length() == 34 && !isReached) {
editText.append("\n");
isReached = true;
}
// if edittext has less than 10chars & boolean has changed, reset
if(editText.getText().length() < 34 && isReached) isReached = false;
Log.d("char", "onTextChanged: "+charSequence);
Log.d("i", "onTextChanged: "+i);
Log.d("i1", "onTextChanged: "+i1);
Log.d("i2", "onTextChanged: "+i2);
}
#Override
public void afterTextChanged(Editable editable) {
}
});
}
this code is not working like i want it to or you can say i'm not being able to code the way i want editText to act.
i want my editText to work like Whatsapp's editText like when i type something and it reaches to the icon inside the editText, cursor goes to a new line with the typing word. In my editText the words are going underneath the ImageButton which im using as a send icon. i dont want the words to go underneath the send icon. Please Help.
ImageButton
<android.support.v7.widget.AppCompatImageButton
android:id="#+id/itemSendButton_id"
android:layout_width="25dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="11dp"
android:background="#color/colorFacebookBtnText"
android:clickable="true"
android:focusable="true"
android:scaleType="fitCenter"
android:src="#drawable/ic_send" />
i'm new to programming so please help me out and thanks in advance.
Use this
et1.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start,int before, int count)
{
// TODO Auto-generated method stub
if(et1.getText().toString().length()==size) //size as per your requirement
{
et2.requestFocus();
}
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
I am working on android application in my application there are registration page in that page i am using #slackid, when user fill the registration form and enter slack id without # its show validation message like # is necessary. Than he move to the next. Kindly please tell me how i use this # validation message. Here is the code
activity_registration.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".RegisterActivity">
<EditText
android:id="#+id/name_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Your Name"/>
<EditText
android:id="#+id/email_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Your email id"
android:inputType="textEmailAddress"/>
<EditText
android:id="#+id/slackid_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint=" #slackId"/>
<EditText
android:id="#+id/password_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="Password"/>
<EditText
android:id="#+id/confirm_password_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="Retype Password"/>
<EditText
android:id="#+id/info_reg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Information/Phone no/Optional"/>
<Button
android:id="#+id/register_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/colorAccent"
android:text="Register"/>
</LinearLayout>
RegistrationActivity.java
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
private EditText name,emailId,slackId,password,conPasword,info;
private Button registerB;
// Alert dialog
AlertDialog.Builder alertBuilder;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
name = findViewById(R.id.name_reg);
emailId = findViewById(R.id.email_reg);
slackId = findViewById(R.id.slackid_reg);
password = findViewById(R.id.password_reg);
conPasword = findViewById(R.id.confirm_password_reg);
info = findViewById(R.id.info_reg);
registerB = findViewById(R.id.register_reg);
//set register to onClick event
registerB.setOnClickListener(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.register_reg:
// Check all requir field empty or not
//Apply the validation in each field including slack Id
if(name.getText().toString().length()==0) {
name.setError("Name cannot be blank");
}
if(emailId.getText().toString().equals("")) {
emailId.setError("Email cannot be blank");
}
if(String.valueOf(slackId.getText().toString().charAt(0)).equals("#")) {
slackId.setError("Slack id cannot be blank");
}
if (password.getText().toString().equals("")) {
password.setError("password cannot be blank");
}
if(conPasword.getText().toString().equals("")) {
conPasword.setError("confirm password cannot be blank");
// if any of the required field empty "Show Dialog to fill the required field
alertBuilder = new AlertDialog.Builder(RegisterActivity.this);
alertBuilder.setTitle("Something Wrong");
alertBuilder.setMessage("Please Fill all required field");
alertBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
AlertDialog alertDialog = alertBuilder.create();
alertDialog.show();
}else if(!(password.getText().toString().equals(conPasword.getText().toString()))){
//check pasword and confirm pasword mismatch
alertBuilder = new AlertDialog.Builder(RegisterActivity.this);
alertBuilder.setTitle("Something Wrong");
alertBuilder.setMessage("Pasword Mismatch");
alertBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
password.setText("");
conPasword.setText("");
}
});
AlertDialog alertDialog = alertBuilder.create();
alertDialog.show();
}else{
// Background task to insert user information into database
BackgroundLoginTask backgroundLoginTask = new BackgroundLoginTask(RegisterActivity.this);
backgroundLoginTask.execute("register",name.getText().toString(),
emailId.getText().toString(),
slackId.getText().toString(),
password.getText().toString(),
info.getText().toString());
}
break;
}
}
}
Try :
edittext.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(!edittext.getText().toString().contains("#")) {
edittext.setError("# not detected");
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
If you want something that the id should start with # then can use this pattern : ^#.*
You can blank validation by using TextUtils.isEmpty(slackId.getText().toString())
This will check if text is null or empty
In your code you did validation like
if(String.valueOf(slackId.getText().toString().charAt(0)).equals("#")) {
slackId.setError("Slack id cannot be blank");
}
this will not validate weather is contains # or not.
do this:
if(!slackId.getText().toString().contains("#")){
//show your error message here
}
Hope it will help you!!
You can make a validation like
if(!slackId.getText().toString().contains("#")){}
You can use this as its better than using textChange listener for your case to check the text edit after losing focus , which will give you the needed validation without submitting .
EditText ed= (EditText) findViewById(R.id.edittxt);
ed.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus && !ed.getText().toString().contains("#")) {
ed.setError("# not detected")
}
}
});
Can someone help with this? My EditText is not empty but the toast still shows up. My app require users to select Date and Time, then select 1 item on the listview to proceed. A dialog will pop out after that. However for some reason, even though my edittext isn't empty, it still won't allow me to continue. I can't seem to figure out what's wrong, I mean the code is just that simple, nothing complicate.
final String date = textDate1.getText().toString().trim();
final String time = textTime1.getText().toString().trim();
listViewHistory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Team team = teams.get(i);
if(TextUtils.isEmpty(date)){
Toast.makeText(RecreateActivity.this,"Please choose a date.",Toast.LENGTH_LONG).show();
return;
}
if(TextUtils.isEmpty(time)){
Toast.makeText(RecreateActivity.this,"Please choose a time.",Toast.LENGTH_LONG).show();
return;
}
//the rest of the code
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(RecreateActivity.this);
LayoutInflater inflater = getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.confirm_layout, null);
dialogBuilder.setView(dialogView);
final Button buttonYes2 = (Button) dialogView.findViewById(R.id.buttonYes2);
final Button buttonNo2 = (Button) dialogView.findViewById(R.id.buttonNo2);
//final Team team = teams.get();
final AlertDialog b = dialogBuilder.create();
b.show();
buttonYes2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
databaseMembers.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final ArrayList<String> CheckList = new ArrayList<String>();
for (DataSnapshot check : dataSnapshot.child("teams").getChildren()) {
CheckList.add(check.getKey());
}
if (CheckList.contains(team.getTeamName())) {
Toast.makeText(RecreateActivity.this, "Team already exist.", Toast.LENGTH_LONG).show();
return;
}
databaseMembers.child("History").child(team.getTeamName()).child("date").setValue(date);
databaseMembers.child("History").child(team.getTeamName()).child("time").setValue(time);
for (DataSnapshot history : dataSnapshot.child("History").child(encodedEmailAddress).getChildren()) {
String key = history.getKey();
if (key.equals(team.getTeamName())) {
teams.clear();
Team team = history.getValue(Team.class);
teams.add(team);
databaseTeams.child(team.getTeamName()).setValue(team);
}
if (key.equals("teamMember")) {
for (DataSnapshot members : dataSnapshot.child("History").child(encodedEmailAddress).child("teamMember").getChildren()) {
String key2 = members.getKey();
String value = members.getValue(String.class);
Map<String, Object> map = new HashMap<>();
map.put(key2, value);
databaseMembers.child("members").child(team.getTeamName()).child("teamMember").updateChildren(map);
b.dismiss();
}
}
}
Toast.makeText(RecreateActivity.this, "Team created.", Toast.LENGTH_LONG).show();
Intent myIntent = new Intent(RecreateActivity.this,
MainActivity.class);
startActivity(myIntent);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
}
XML:
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Previous Team"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textAlignment="center"/>
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Select new Date/Time and tap on the Team."
android:textAlignment="center"/>
<ListView
android:id="#+id/listViewHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
</ListView>
<TextView
android:id="#+id/textView5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Members:"
android:textAppearance="#style/TextAppearance.AppCompat.Headline" />
<TextView
android:id="#+id/textViewList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:textAppearance="#style/TextAppearance.AppCompat.Medium" />
<EditText
android:id="#+id/textDate1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Select Date..."
android:layout_alignParentStart="true" />
<EditText
android:id="#+id/textTime1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Select Time..."
android:layout_below="#+id/textDate"
android:layout_alignParentStart="true" />
<Button
android:id="#+id/buttonAddHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Team"
android:textAlignment="center"
android:textAllCaps="false"
tools:textSize="20sp" />
You are getting string from EditText only once - before setting OnItemClickListener. You need to get string inside the listener.
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Team team = teams.get(i);
final String date = textDate1.getText().toString().trim();
final String time = textTime1.getText().toString().trim();
if(TextUtils.isEmpty(date)){
Toast.makeText(RecreateActivity.this,"Please choose a date.",Toast.LENGTH_LONG).show();
return;
}
if(TextUtils.isEmpty(time)){
Toast.makeText(RecreateActivity.this,"Please choose a time.",Toast.LENGTH_LONG).show();
return;
}
}
Your field is initialized only once. I don't know the context, this may be actually what you want, but then it doesn't make any sense to validate it every time, those fields have the same value every time the listener code is run. Try to add the code to get date and time in the listener itself.
Your code is setting [date] and [time] outside of the onClickListener. When the user clicks the button, your code isn't resetting the variables. I'd evaluate the EditText directly from your onClickListener code:
listViewHistory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Team team = teams.get(i);
if(TextUtils.isEmpty(textDate1.getText().toString().trim())){
Toast.makeText(RecreateActivity.this,"Please choose a date.",Toast.LENGTH_LONG).show();
return;
}
if(TextUtils.isEmpty(textTime1.getText().toString().trim())){
Toast.makeText(RecreateActivity.this,"Please choose a time.",Toast.LENGTH_LONG).show();
return;
}
Try getting date value of edittext inside the click listener.
listViewHistory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final Team team = teams.get(i);
final String date = textDate1.getText().toString().trim();
final String time = textTime1.getText().toString().trim();
if(date.isEmpty()){
Toast.makeText(RecreateActivity.this,"Please choose a date.",Toast.LENGTH_LONG).show();
return;
}
if(time.isEmpty()){
Toast.makeText(RecreateActivity.this,"Please choose a time.",Toast.LENGTH_LONG).show();
return;
}
Imagine a number 10, then after user clicks a button it changes to 100. But how to make an efficient transition
10 -> 100,
that will display values like
12, 15, 18, ..., 97, 100 over 1 second.
I've seen something like that in "Cookie clicker" but couldn't find anything about that kind of transition in the source code.
I had an idea of a loop (for number1 < number2, do number1++), it will work fine for small numbers, but if 10 changes to 1 billion, then the loop will probably freeze the whole app.
Second idea is to get added value (100-10=90) and divide by 30 or 60 frames, and add this value with each frame. But what will happen if frame is dropped? - Probably value will not be added. What if user makes double click or the system adds values automatically?
Hope it gives an idea of what kind of number transition I need.
Maybe I overlooked and there is a simple approach? Any help is appreciated.
Hope this little demo using a ValueAnimator will inspire you to find an appropriate solution.
You can specify the duration of the animation (see code) and even adjust the frame-rate by saying mAnimator.setFrameDelay(frameDelay);.
By using animator.isRunning() or animator.isStarted() you can prevent double-click malfunction or other unwanted behaviour while the current animation is runnning.
The Main Activity:
/** ValueAnimator demo */
public class MainActivity extends Activity {
ValueAnimator mAnimator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv = (TextView) findViewById(R.id.textview);
mAnimator = ValueAnimator.ofInt(1, 100).setDuration(1000);
mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
final Integer value = (Integer) animator.getAnimatedValue();
tv.setText(String.format("%04d", value));
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animator) {
super.onAnimationEnd(animator);
final int endValue = Integer.parseInt((String) tv.getText());
mAnimator.setIntValues(endValue, endValue + 100);
}
});
}
/** Button callback */
public void onClick(final View view) {
if (!mAnimator.isStarted() && !mAnimator.isRunning()) {
mAnimator.start();
}
}
}
Simple demo layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:typeface="monospace"
android:text="0001" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gimme +100"
android:onClick="onClick">
</Button>
Here's another demo (hope this answers your 2. question), which implements different behaviour dependent on single click or double-click on the button. Just experiment with it, you now have the basic building blocks to construct own behavour ...
/** ValueAnimator demo */
public class MainActivity extends Activity {
ValueAnimator mAnimator;
TextView mTv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = (TextView) findViewById(R.id.textview);
mAnimator = ValueAnimator.ofInt(1, 100).setDuration(1000);
mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
final Integer value = (Integer) animator.getAnimatedValue();
mTv.setText(String.format("%04d", value));
}
});
final Button button = (Button) findViewById(R.id.button);
final GestureDetector gestureDetector = new GestureDetector(this,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
performAnimation(100);
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
performAnimation(0);
return true;
}
});
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
}
/** starts animation */
private void performAnimation(final int offset) {
if (!mAnimator.isStarted() && !mAnimator.isRunning()) {
final int endValue = Integer.parseInt((String) mTv.getText());
mAnimator.setIntValues(endValue + offset, endValue + 100 + offset);
mAnimator.start();
}
}
}
Don't forget to replace your layout file, since the click-attribute of the button has been removed:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:typeface="monospace"
android:text="0001" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gimme +100" >
</Button>
</LinearLayout>
I guess you can do it by using different threads. Only main thread works with UI so you can divide the interval into small intervals and make a transitions in different threads.After send them to main thread and print. Hope it will help.
I create simple Android app (https://www.linux.com/learn/docs/683628-android-programming-for-beginners-part-1) with latest Android Studio. Code:
public class test_act extends Activity {
private static final int MILLIS_PER_SECOND = 1000;
private static final int SECONDS_TO_COUNTDOWN = 30;
private android.widget.TextView countdownDisplay;
private android.os.CountDownTimer timer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.full_act);
countdownDisplay = (android.widget.TextView) findViewById(R.id.time_display_box);
android.widget.Button startButton = (android.widget.Button) findViewById(R.id.startbutton);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
try {
showTimer(SECONDS_TO_COUNTDOWN * MILLIS_PER_SECOND);
} catch (NumberFormatException e) {
// method ignores invalid (non-integer) input and waits
// for something it can use
}
}
});
}
private void showTimer(int countdownMillis) {
if(timer != null) { timer.cancel(); }
timer = new android.os.CountDownTimer(countdownMillis, MILLIS_PER_SECOND) {
#Override
public void onTick(long millisUntilFinished) {
countdownDisplay.setText("counting down: " +
millisUntilFinished / MILLIS_PER_SECOND);
}
#Override
public void onFinish() {
countdownDisplay.setText("KABOOM!");
}
}.start();
}
}
My XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/time_display_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:text="#string/_00_30"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<Button
android:id="#+id/startbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/time_display_box"
android:layout_centerHorizontal="true"
android:layout_marginTop="41dp"
android:text="#string/start" />
</RelativeLayout>
In emulator it's good working. But on my Galaxy S2 with CyanogenMod10.1(Android 4.2.2) app wrong updating TextView. Screenshot:
How I can resolve this problem?
upd: after screen rotate TextView is updating once.
You might want to try invalidating your layout every time it is updated. I am guessing with how often the text is being updated the phone is not having enough time to redraw the layout. This would also explain why it works when you rotate your phone, because then the layout is forced to update.
countdownDisplay.invalidate();
Let me know if that does not work.
It commonly happens when you put UI updates inside try blocks, try to avoid it or wrap with runOnUiThread.
EDIT:
Another reason - you update it to fast - you code does 1000 updates per second i dont think it can handle it.