I have to create a Stack-bar graph and my requirement is to graph should look like this.
I have checked many graph libraries but no one is providing this type of UI.
is this possible to achieve?
So I finally found a way for that.
Step 1: Add 3 views with respective colors and a button like in below XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".MainActivity">
<View
android:layout_width="75sp"
android:layout_height="15sp"
android:layout_marginTop="100sp"
android:layout_marginStart="10sp"
android:background="#ff0000"
android:id="#+id/viewOverdue"/>
<View
android:layout_width="75sp"
android:layout_height="15sp"
android:layout_marginTop="100sp"
android:layout_marginStart="2sp"
android:background="#FFDD00"
android:layout_toEndOf="#+id/viewOverdue"
android:id="#+id/viewActive"/>
<View
android:layout_width="75sp"
android:layout_height="15sp"
android:layout_marginTop="100sp"
android:layout_marginStart="2sp"
android:background="#00FF00"
android:layout_toEndOf="#+id/viewActive"
android:id="#+id/viewDone"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Overdue"
android:id="#+id/editOverdue"
android:layout_below="#+id/viewActive"
android:layout_marginTop="100sp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Active"
android:layout_below="#+id/editOverdue"
android:id="#+id/editActive"
android:layout_marginTop="2sp"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Done"
android:layout_below="#+id/editActive"
android:id="#+id/editDone"
android:layout_marginTop="2sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="submit"
android:id="#+id/btnSubmit"
android:layout_below="#id/editDone"
android:layout_marginTop="20sp"/>
</RelativeLayout>
This is how it will Look:
Do note that views are set to invisible initially.
Step 2: The coding part:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private EditText typeActive, typeDone, typeOverdue;
private Button btnSubmit;
private View viewDone, viewOverDue, viewActive;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
typeActive = findViewById(R.id.editActive);
typeDone = findViewById(R.id.editDone);
typeOverdue = findViewById(R.id.editOverdue);
btnSubmit = findViewById(R.id.btnSubmit);
viewDone = findViewById(R.id.viewDone);
viewActive = findViewById(R.id.viewActive);
viewOverDue = findViewById(R.id.viewOverdue);
viewDone.setVisibility(View.INVISIBLE);
viewOverDue.setVisibility(View.INVISIBLE);
viewActive.setVisibility(View.INVISIBLE);
//Type all the number of tasks and press the submit button
btnSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String tasksActive = typeActive.getText().toString();
final String tasksDone = typeDone.getText().toString();
final String tasksOverdue = typeOverdue.getText().toString();
int intTaskActive = Integer.parseInt(tasksActive);
int intTaskDone = Integer.parseInt(tasksDone);
int intTaskOverdue = Integer.parseInt(tasksOverdue);
int totalTasks = intTaskActive + intTaskOverdue + intTaskDone;
float percentageActive = (intTaskActive*100.0f)/totalTasks;
float percentageDone = (intTaskDone*100.0f)/totalTasks;
float percentageOverdue = (intTaskOverdue*100.0f)/totalTasks;
int intPercActive = (int)percentageActive;
int intPercDone = (int)percentageDone;
int intPercOverdue = (int)percentageOverdue;
viewDone.setVisibility(View.VISIBLE);
viewOverDue.setVisibility(View.VISIBLE);
viewActive.setVisibility(View.VISIBLE);
viewDone.setLayoutParams(new RelativeLayout.LayoutParams(intPercDone*10, 50));
viewActive.setLayoutParams(new RelativeLayout.LayoutParams(intPercActive*10, 50));
viewOverDue.setLayoutParams(new RelativeLayout.LayoutParams(intPercOverdue*10, 50));
}
});
}
}
This is the output after execution:
So how this works is you type the number of tasks in the edittext. It doesn't matter how you get the number of tasks but you need to convert it to percentage of total length of the stackBar or whatever you call it.
So finally you just assign each view the respective width as per the number.
Related
Im currently working on a small project. Which has a textview, a button and a edittext. The textview is set to 1 and when the button is clicked the textview goes up by 1. I can fill the edittext with any number (including -1 for example). I need to get the value from the edittext and add it to the current value in the textview with the click of the same button. How do i do this? this sounds really easy but i cant seem to find a solution.
MainActivity
package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int numberText = 1;
EditText editTextID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textViewID = (TextView) findViewById(R.id.textViewID);
textViewID.setText("1");
}
public void changeValue(View view){
numberText+=1;
TextView textViewID = (TextView) findViewById(R.id.textViewID);
textViewID.setText(numberText+"");
}
}
Activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
tools:context="com.example.myapplication.MainActivity">
<TextView
android:id="#+id/textViewID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.238" />
<Button
android:id="#+id/PlusID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="changeValue"
android:text="#string/plus"
tools:ignore="MissingConstraints"
android:layout_marginTop="50dp"
app:layout_constraintTop_toBottomOf="#+id/textViewID"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="#+id/textViewID"
android:layout_marginRight="0dp"
app:layout_constraintRight_toRightOf="#+id/textViewID" />
<EditText
android:id="#+id/editTextID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintTop_toBottomOf="#+id/PlusID"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="#+id/PlusID"
android:layout_marginRight="0dp"
app:layout_constraintRight_toRightOf="#+id/PlusID" />
</android.support.constraint.ConstraintLayout>
You can get EditText value as follows within changeValue:
EditText editTextID = (EditText ) findViewById(R.id.editTextID);
try {
int editValue = Integer.parseInt(editTextID.getText().toString());
} catch (NumberFormatException e) {
// edit text value not a valid integer
}
Then it should be simple to add editValue to numberText and display in the TextView.
Here is how:
public void changeValue(View view) {
// Retrieve the content from EditText
editTextID = (EditText) findViewById(R.id.edit_text);
String content = editTextID.toString();
// Then the value of that content
// Wrap below statement in a try-catch for a NumberFormatException
int value1 = Integer.parseInt(content);
// Add it to value from TextView
TextView textViewID = (TextView) findViewById(R.id.textViewID);
// Wrap below statement in a try-catch for a NumberFormatException
int value2 = Integer.parseInt(textViewID.toString());
// Finally set the correct value
int value = value1 + value2;
textViewID.setText(value + "");
}
Also, store the references to TextView and EditText as class fields rather than calling findViewById() again.
int currentNum=Integer.parseInt(textView.getText().toString());
int addedNum=Integer.valueOf(editText.getText().toString());
currentNum+=addedNum;
textView.setText(String.valueOf(currentNum));
Try initialising the required views first & storing the View instances... It would make your task a lot easier.
public class MainActivity extends AppCompatActivity {
private TextView displayValueTextView;
private EditText valueEditText;
private Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
displayValueTextView = (TextView) findViewById(R.id.tv_value);
valueEditText = (EditText) findViewById(R.id.et_input);
button = (Button) findViewById(R.id.button);
}
}
Here's the XML layout so you don't get confused about the Views and their associated Id's;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/rl_activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.android.myapplication.MainActivity">
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="26sp"
android:layout_centerInParent="true"
android:maxLines="1"
android:text="Hello World"/>
<EditText
android:id="#+id/et_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:ems="9"
android:hint="#string/hint_text"
android:maxLines="1"/>
<Button
android:id="#+id/button"
android:text="#string/plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="changeValue"
android:layout_toRightOf="#+id/et_input"
android:layout_alignBottom="#+id/et_input"/>
</RelativeLayout>
The onClick attribute of the Button is set to changeValue this is our method that will change the value of our TextView, dependent on what number is on your EditText. This method is shown below:
public void changeValue(View view) {
double numberToAdd;
double currentValue;
try {
numberToAdd = Double.parseDouble(valueEditText.getText().toString());
} catch (Exception ex) {
ex.printStackTrace();
Toast.makeText(this, "Edit Text must contain a number.", Toast.LENGTH_LONG).show();
valueEditText.setText("");
numberToAdd = 0;
}
try {
currentValue = Double.parseDouble(displayValueTextView.getText().toString());
} catch (Exception ex) {
ex.printStackTrace();
currentValue = 0;
Toast.makeText(this, "Current value is not a number. It is now set to 0.", Toast.LENGTH_LONG).show();
displayValueTextView.setText("0");
}
double finalValue = currentValue + numberToAdd;
displayValueTextView.setText(finalValue + "");
}
The numberToAdd variable is the number we are adding to our current TextView... We must;
Extract the value the EditText holds by getting it's text and parsing it as a double (this will allow us to handle decimals numbers in the EditText).
We then extract the current value of our TextView (if it is not a number an exception will be thrown and the textview will default to 0).
Finally we add the two values and set the TextView as the string representing the added values.
As the title says, I get this error while interacting with a Spinner. I've noticed that there are many post about this argument, but every one is different from each other (answers too). Unfortunately, I didn't find a solution, so I'm asking here.
Here is a screenshot of the Spinner:
As you can see, the first Spinner is ok, but the second has two problems:
First one, it doesn't show values
Second one, when I tap the spinner, nothing happen. If I tap again the spinner, I get the error "Attempted to finish an input event but the input event receiver has already been disposed."
Maybe the two things are connected somehow...
Here is the code:
public class Settings extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
Integer[] radiusArray = new Integer[]{500,700,1000,1500,2000,2500,3000,4000,5000};
Integer[] geofenceRadius = new Integer[]{100,200,300,400,500};
try {
final Spinner spinnerRA = (Spinner) findViewById(R.id.search_radius);
final Spinner spinnerGR = (Spinner) findViewById(R.id.geofence_radius);
ArrayAdapter<Integer> adapterRA = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, radiusArray);
spinnerRA.setAdapter(adapterRA);
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerRA.setAdapter(adapterGR);
//Getting from preference files, saved settings, if any
//1000 and 100 are default settings
final SharedPreferences sharedPref = getSharedPreferences("Settings",Context.MODE_PRIVATE);
String temp = getResources().getString(R.string.search_radius);
int savedRadius = sharedPref.getInt(temp, 1000);
temp = getResources().getString(R.string.geofence_radius);
int savedGeofence = sharedPref.getInt(temp, 100);
//Show selected value for spinner, or default value
int i;
for(i=0; i<radiusArray.length; i++){
if(radiusArray[i].equals(savedRadius)){
break;
}
}
spinnerRA.setSelection(i);
for(i=0; i<geofenceRadius.length; i++){
if(geofenceRadius[i].equals(savedGeofence)){
break;
}
}
spinnerGR.setSelection(i);
Button Save = (Button) findViewById(R.id.save_settings_button);
Save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer searchRadius = (Integer)spinnerRA.getSelectedItem();
Integer geofenceRadius = (Integer)spinnerGR.getSelectedItem();
//Saving new value of search_radius
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.search_radius),searchRadius);
editor.putInt(getString(R.string.geofence_radius),geofenceRadius);
editor.putBoolean(getString(R.string.initialized),true);
editor.commit();
CharSequence text = "Changes saved succesfully!";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getApplicationContext(), text, duration);
toast.show();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
And here is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Settings"
android:textSize="14pt"
android:layout_marginTop="8pt"
android:gravity="center"/>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5pt"
android:id="#+id/second_gray_line"
android:background="#android:color/darker_gray"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10pt">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Initial search radius (in meters):"
android:textColor="#FF8500"
android:layout_marginLeft="10pt"
android:layout_marginTop="15pt"
android:textSize="11pt"/>
<Spinner
android:layout_width="60pt"
android:layout_height="wrap_content"
android:id="#+id/search_radius"
android:layout_marginTop="5pt"
android:layout_marginLeft="5pt">
</Spinner>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10pt">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Location radius (in meters):"
android:textColor="#FF8500"
android:layout_marginLeft="10pt"
android:layout_marginTop="15pt"
android:textSize="11pt"/>
<Spinner
android:layout_width="60pt"
android:layout_height="wrap_content"
android:id="#+id/geofence_radius"
android:layout_marginTop="5pt"
android:layout_marginLeft="5pt">
</Spinner>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/save_settings_button"
android:text="Save Settings"
android:textSize="10pt"
android:layout_gravity="center"
android:layout_marginTop="50pt"/>
</LinearLayout>
I think it's a really stupid error, but I can't figure out what causes it. Could you help me? Thank you!
I solved and, as I said, the error was really stupid... I made a mistake here, in the second adapter:
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerRA.setAdapter(adapterGR);
This must be changed in:
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerGR.setAdapter(adapterGR);
It was just an oversight. I was setting the second adapter using spinnerRA instead of spinnerGR. Now it works!
This is my first app. I had been setting a preference in an activity (with a fragment), but I want to move the fragment to a DialogPreference. It migrated okay, except my text colors have gone weird. See picture. The text should just be black, not white and gray. Any idea what I got wrong?
(Sorry, I know this is pretty sloppy code)
How it looks now:
My xml...
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relLay_dialog_semester_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<TextView
android:id="#+id/select_semester_prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/select_semester_prompt" />
<LinearLayout
android:id="#+id/linLayGradeSum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/select_semester_prompt"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp" >
<Spinner
android:id="#+id/semester_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="3"
android:hint="#string/hint_editSemester" />
<Spinner
android:id="#+id/year_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4" />
</LinearLayout>
<TextView
android:id="#+id/active_semesters_str"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/linLayGradeSum"
android:layout_below="#+id/linLayGradeSum"
android:text="#string/active_semester_str"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="#+id/active_semesters_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/active_semesters_str"
android:layout_below="#+id/active_semesters_str"
android:layout_marginTop="10dp"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
My extended DialogPreference class
public class SemesterDialogPreference extends DialogPreference {
SharedPreferences settings;
public static int YEAR_DEFAULT_VALUE = Activity_AddCourse.thisYear - Activity_AddCourse.baseYear;
public static int SEASON_DEFAULT_VALUE = Semester.getDefaultSemester().getSeasonInt();
public static int SEMESTER_DEFAULT_ID = 1;
String semester_id_key;
DBAdapter db;
// this is where I do everything view-related
#Override
public void onBindDialogView(View view){
settings = getSharedPreferences();
int curSemesterId = settings.getInt(semester_id_key, 1);
db = new DBAdapter(this.getContext().getApplicationContext());
db.open();
Semester curSemester = db.getSemester(curSemesterId);
db.close();
ArrayList<String> years = new ArrayList<String>();
for (int i = Activity_AddCourse.baseYear; i <= Activity_AddCourse.maxYear; i++)
{
years.add(Integer.toString(i));
}
ArrayAdapter<String> adapter_year = new ArrayAdapter<String>(this.getContext().getApplicationContext(),
android.R.layout.simple_spinner_item, years);
Spinner spinYear = (Spinner)view.findViewById(R.id.year_spinner);
adapter_year.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinYear.setAdapter(adapter_year);
spinYear.setSelection(curSemester.getYear() - Activity_AddCourse.baseYear);
Spinner spinner = (Spinner) view.findViewById(R.id.semester_spinner);
ArrayAdapter<CharSequence> adapter_spinner = ArrayAdapter.createFromResource(this.getContext().getApplicationContext(),
R.array.semester_spinner, android.R.layout.simple_spinner_item);
adapter_spinner.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter_spinner);
spinner.setSelection(Semester.seasonStringToInt(curSemester.getSeason()));
db = new DBAdapter(this.getContext().getApplicationContext());
db.open();
Semester[] s = db.getAllSemesters();
db.close();
String activeSem;
LinearLayout semesterList = (LinearLayout) view.findViewById(R.id.active_semesters_list);
if(s != null){
for(int i = 0; i < s.length; i++){
activeSem = s[i].getSemesterString();
TextView tv = (TextView) new TextView(this.getContext().getApplicationContext());
tv.setText(activeSem);
semesterList.addView(tv);
System.out.println(s[i].getSemesterString());
}
}
super.onBindDialogView(view);
}
public SemesterDialogPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.dialog_set_semester);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
persistBoolean(positiveResult);
}
}
UPDATE:
The DialogPreference pops up from my settings activity, as shown below.
public class SettingsActivity extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
}
}
Also, I was able to get the spinner text to black by making my own xml layouts for them, just as Huy Tran suggested. However, I had to make one for each the spinner_item and the spinner_dropdown_item. See below.
ArrayAdapter<String> adapter_year = new ArrayAdapter<String>(this.getContext().getApplicationContext(),
R.layout.my_spinner_item, years);
Spinner spinYear = (Spinner)view.findViewById(R.id.year_spinner);
adapter_year.setDropDownViewResource(R.layout.my_spinner_dropdown_item);
Why did I have to do this? I don't know. Also, dropdown items are each now about 50% taller. I copied exactly from source code into my own xml and it still renders differently. Very weird.
Create a layout like below and use that layout in setDropDownViewResource instead of android.R.layout.simple_spinner_dropdown_item.
Create my_spinner_dropdown_item.xml in res/layout:
EDITED:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textColor="#color/black"
/>
my_spinner_item
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />
Try using margin to change the size of each item.
And then in your SemesterDialogPreference:
setDropDownViewResource(R.layout.my_spinner_dropdown_item);
I have a test code using the View Property Animation to switch locations of two buttons. The code is as below:
public class TestAnimationActivity extends Activity {
private View mainView;
private View TempView;
private Button B1, B2, B3;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate your view
setContentView(R.layout.main_test);
mainView = findViewById(R.id.mainTest);
B1 = (Button) mainView.findViewById(R.id.B1);
B2 = (Button) mainView.findViewById(R.id.B2);
B3 = (Button) mainView.findViewById(R.id.B3);
OnClickListener OCL = new OnClickListener(){
#Override
public void onClick(View v) {
if(TempView == null){
TempView = v;
}else{
int originalPos1[] = new int[2];
TempView.getLocationOnScreen( originalPos1 );
int originalPos2[] = new int[2];
v.getLocationOnScreen( originalPos2 );
v.animate().translationX((float)originalPos1[0] - (float)originalPos2[0]);
v.animate().translationY((float)originalPos1[1] - (float)originalPos2[1]);
TempView.animate().translationX((float)originalPos2[0] - (float)originalPos1[0]);
TempView.animate().translationY((float)originalPos2[1] - (float)originalPos1[1]);
TempView = null;
}
}};
B1.setOnClickListener(OCL);
B2.setOnClickListener(OCL);
B3.setOnClickListener(OCL);
}
}
The XML file is as below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainTest"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/B1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#B4B4B4"
android:gravity="center" />
<Button
android:id="#+id/B2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#470047"
android:gravity="center" />
<Button
android:id="#+id/B3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:gravity="center" />
</LinearLayout>
When I was testing this code on my phone. The animation did not work properly.
Two buttons will switch position the first time, but the button will go to wrong position if I continue clicking them. It seems that the button still calculate the position it should move to based on its original location when the app launched.
Anyone knows what is going wrong?
I have a simple activity which needs to accept a 4-digit PIN number using a custom pin-pad (buttons on the screen). The digits are stored in four EditTexts.
When I click a button, the text in the button is stored in a char[] (myEditText.getText() shows that this is happening), the focus is moved to the next EditText through an onFocusListener() and the Log output shows that this is all happening correctly.
11-20 10:19:56.969: I/DebugA(17742): Pin1 updated to: 1 // Pin1 is the ID
11-20 10:19:58.289: I/DebugA(17742): Pin2 updated to: 2 // '2' is Pin2.getText()
11-20 10:19:58.849: I/DebugA(17742): Pin3 updated to: 3
11-20 10:19:59.659: I/DebugA(17742): Pin4 updated to: 4
The screen itself is simply not being updated. The EditTexts all appear empty, even though the code executes perfectly.
I have looked through a whole heap of answers on SO and tried many of the suggestions with absolutely no luck, so I am posting this question which I hope someone can shed some light on! Has anyone else had this happen?
Here's some of the layout file:
<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" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="42dp" >
<EditText
android:id="#+id/Pin1"
android:tag="Pin1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="2"
android:gravity="center_vertical|center_horizontal"
android:nextFocusDown="#+id/Pin2"
android:maxLength="1"
android:inputType="textPassword" />
...
...
...
</RelativeLayout>
...and the buttons are:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="21dp"
android:layout_below="#+id/layout1" >
<Button
android:id="#+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:text="1" />
<Button
android:id="#+id/Button02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:layout_marginLeft="21dp"
android:text="2" />
<Button
android:id="#+id/Button03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:layout_marginLeft="21dp"
android:text="3" />
</LinearLayout>
The activity is a standard activity (MyActivity extends Activity).
Any thoughts?
UPDATE
Here's some of the java as requested:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout layout = (RelativeLayout)inflater.inflate(R.layout.activity_login, null);
EditText Pin1 = (EditText) layout.findViewById(R.id.Pin1);
Pin1.setOnFocusChangeListener(focusListener);
Pin1.setText("1"); // <--THIS HAS NO EFFECT
EditText Pin2 = (EditText) layout.findViewById(R.id.Pin2);
Pin2.setOnFocusChangeListener(focusListener);
EditText Pin3 = (EditText) layout.findViewById(R.id.Pin3);
Pin3.setOnFocusChangeListener(focusListener);
EditText Pin4 = (EditText) layout.findViewById(R.id.Pin4);
Pin4.setOnFocusChangeListener(focusListener);
...
...
...
}
The Onclick method is:
public void btnPinClick(View btnPin) {
String PinNumber = ((Button)btnPin).getText().toString();
RelativeLayout layout = (RelativeLayout)getLayoutInflater().inflate(R.layout.activity_login, null);
ArrayList<View> views = (ArrayList<View>) layout.getFocusables(View.FOCUS_DOWN);
EditText nextItem = null;
for (int i = 0; i < views.size(); i++) {
// THIS IS THE CORRECT EditText FOR EACH OF THESE
EditText textBox = (EditText) views.get(i);
if (textBox.getTag().toString().equals(currentText)) {
textBox.setText(PinNumber);
pin[i] = PinNumber.toCharArray()[0];
Log.i("DebugA", textBox.getTag().toString() + " updated to: " + textBox.getText().toString());
textBox.invalidate();
textBox.refreshDrawableState();
if(i+1 < views.size()) {
nextItem = (EditText) views.get(i+1);
}
else {
doCheckPin();
}
break;
}
}
if(nextItem != null){
nextItem.requestFocus();
currentText = nextItem.getTag().toString();
}
}
UPDATE 2
Here is the code for the OnFocusChangeListener as requested:
protected OnFocusChangeListener focusListener = new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
//THIS SIMPLY SETS A VARIABLE STRING TO SAY WHICH
//EditText HAS FOCUS.
currentText = v.getTag().toString();
}
}
};
It looks like you're using a layout inflater in addition to setContentView in your activity. And affecting the edittexts referenced by the inflater. Try removing use of the inflater and rely solely on setContentView for this part of the activity. You might be performing in an incorrect view hierarchy.