I have a problem with my setOnClickListener method for one of the buttons in my code. What basically happens is that I call a typeFinder inside the setOnClickListener method, but the first time I press the button the values do not get updated. I have used the debugger and from my understanding what happens is that even though the function is called, the program does not actually go through the function until after setOnClickListener, which means when I press the button the second time it has the right values to show from the previous button press. I have tried using TypesTask as well (as seen in commented part at the bottom of the page), but doing so resulted in the same outcome.
Here is the code for the class:
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private DatabaseReference myRef;
private ArrayList<String> recipesList = new ArrayList<String>();
private String[] types = {"pizza", "ice cream", "sandwich", "salad", "steak"};
private void typeFinder(String type) {
myRef.orderByChild("type").equalTo(type).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String word = "";
boolean wordAdded = false;
String value = dataSnapshot.getValue().toString();
for (int i = 0; i < value.length(); i++) {
if (wordAdded == false) {
if (value.charAt(i) == '=') {
recipesList.add(word);
wordAdded = true;
word = "";
} else if (value.charAt(i) != '{' && value.charAt(i) != ',') {
if (word.length() == 0 && value.charAt(i) == ' ') {
} else {
word = word + value.charAt(i);
}
}
}
if (value.charAt(i) == '}')
if (i + 2 == value.length()) {
wordAdded = false;
break;
} else
wordAdded = false;
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
myRef = FirebaseDatabase.getInstance().getReference();
Button saladsB = (Button) findViewById(R.id.saladButton);
Button pizzaB = (Button) findViewById(R.id.pizzaButton);
Button iceCreamB = (Button) findViewById(R.id.iceCreamButton);
Button steakB = (Button) findViewById(R.id.steakButton);
Button sandwichB = (Button) findViewById(R.id.sandwichButton);
final TextView testTextView = (TextView) findViewById(R.id.test_text_view);
testTextView.setText(Integer.toString(recipesList.size()));
super.onCreate(savedInstanceState);
saladsB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// recipesList.clear();
// t.typeFinder("salad")
typeFinder("salad");
// new TypesTask().execute("salad");
String recipes = "";
for (int i = 0; i < recipesList.size(); i++) {
recipes = recipes + recipesList.get(i) + "\n";
}
testTextView.setText(recipes);
// Intent intent = new Intent(MainActivity.this, ListviewActivity.class);
// intent.putStringArrayListExtra("FOOD_LIST", recipesList);
// startActivity(intent);
}
});
}
/*
public class TypesTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
myRef = FirebaseDatabase.getInstance().getReference();
}
#Override
protected Void doInBackground(String... params) {
typeFinder(params[0]);
return null;
}
}
*/
}
Here is the xml for the page
<?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.thevash.recipes.MainActivity">
<LinearLayout
android:layout_width="0dp"
android:layout_height="810dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="458dp"
android:orientation="horizontal"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintTop_creator="1">
<TextView
android:id="#+id/test_text_view"
android:layout_width="585dp"
android:layout_height="248dp"
android:layout_weight="1"
android:text="TextView"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="-377dp" />
</LinearLayout>
<Button
android:id="#+id/saladButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="Salads"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="5dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/pizzaButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="Pizzas"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="52dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/iceCreamButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="ice cream"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="#+id/pizzaButton"
app:layout_constraintTop_toBottomOf="#+id/pizzaButton"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="#+id/pizzaButton" />
<Button
android:id="#+id/steakButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="steaks"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="#+id/iceCreamButton"
app:layout_constraintTop_toBottomOf="#+id/iceCreamButton"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="#+id/iceCreamButton" />
<Button
android:id="#+id/sandwichButton"
android:layout_width="0dp"
android:layout_height="48dp"
android:text="sandwiches"
tools:layout_constraintTop_creator="1"
tools:layout_constraintRight_creator="1"
app:layout_constraintRight_toRightOf="#+id/steakButton"
app:layout_constraintTop_toBottomOf="#+id/steakButton"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="#+id/steakButton" />
</android.support.constraint.ConstraintLayout>
you can do this using TypesTask but you need to modify TypesTask class like below
public class TypesTask extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
myRef = FirebaseDatabase.getInstance().getReference();
}
#Override
protected Void doInBackground(String... params) {
typeFinder(params[0]);
return null;
}
#Override
onPostExecute(Void result){
String recipes = "";
for (int i = 0; i < recipesList.size(); i++) {
recipes = recipes + recipesList.get(i) + "\n";
}
testTextView.setText(recipes);
}
}
and your onClick should be like this
saladsB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new TypesTask().execute("salad");
}
});
As mentioned in the comments both of the answers provided work. I either had to add the UI update to the typeFinder function itself, or use AsyncTask to update the UI inside onPostExecute method. For the latter I had to put the program to sleep for one second after the line typeFinder(params[0]) to give it enough time to update the variables.
Your method in which you are building the reciepeList is an asynchronous call. You need to update the changes to Ui after the OnSuccess() call of EventListener. Relocate the Ui updation code to OnDataChange See the code below :
private void typeFinder(String type) {
myRef.orderByChild("type").equalTo(type).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String word = "";
boolean wordAdded = false;
String value = dataSnapshot.getValue().toString();
for (int i = 0; i < value.length(); i++) {
if (wordAdded == false) {
if (value.charAt(i) == '=') {
recipesList.add(word);
wordAdded = true;
word = "";
} else if (value.charAt(i) != '{' && value.charAt(i) != ',') {
if (word.length() == 0 && value.charAt(i) == ' ') {
} else {
word = word + value.charAt(i);
}
}
}
if (value.charAt(i) == '}')
if (i + 2 == value.length()) {
wordAdded = false;
break;
} else
wordAdded = false;
}
// Update the Ui Here
String recipes = "";
for (int i = 0; i < recipesList.size(); i++) {
recipes = recipes + recipesList.get(i) + "\n";
}
this.testTextView.setText(recipes);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
Related
I am making one simple bank transfer Android application with Google voice input. So, basically, in my app I have created one method layoutclicked() for number of clicks on the layout. I have initialized numberOfclicks as 0 initially, so when user taps on the screen it increments. It will start voice input as well.
public void layoutClicked(View view)
{
if(IsInitialVoiceFinshed) {
numberOfClicks++;
listen();
}
}
I have created switch case statement for filling the input field, so like when case is 1, i.e user tap on the screen one time, then it will start voice input and user tell the details. It will set that text to that input field. And, again, in case 2 it will do another task.
If the user does not say anything in the first case, the field will be empty. And in case 2, they will go to another field. I want to fill that first input field. Can we achieve this by using for loop?
Here is my complete Java code
package org.tensorflow.lite.examples.detection;
import android.annotation.SuppressLint;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
public class Banktransfer extends AppCompatActivity {
private TextToSpeech tts;
private TextView status;
private TextView To;
private TextView Subject;
private TextView To1;
private int numberOfClicks;
static String to;
float x1,x2;
private boolean IsInitialVoiceFinshed;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bank_transfer);
IsInitialVoiceFinshed = false ;
tts = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
int result = tts.setLanguage(Locale.UK);
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "This Language is not supported");
}
tts.speak("Welcome to Bank transfer. tap on the screen , Tell me the IFSC code of bank",TextToSpeech.QUEUE_FLUSH,null);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
IsInitialVoiceFinshed=true;
}
}, 8500);
} else {
Log.e("TTS", "Initilization Failed!");
}
}
});
status = (TextView)findViewById(R.id.status);
To = (TextView) findViewById(R.id.to);
Subject = findViewById(R.id.subject);
To1 = (TextView) findViewById(R.id.to1);
numberOfClicks = 0;
}
#Override
public void onDestroy() {
if (tts != null) {
tts.stop();
tts.shutdown();
}
super.onDestroy();
}
public void layoutClicked(View view)
{
if(IsInitialVoiceFinshed) {
numberOfClicks++;
listen();
}
}
private void listen(){
Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Say something");
try {
startActivityForResult(i, 100);
} catch (ActivityNotFoundException a) {
Toast.makeText(Banktransfer.this, "Your device doesn't support Speech Recognition", Toast.LENGTH_SHORT).show();
}
}
#SuppressLint("SetTextI18n")
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 100&& IsInitialVoiceFinshed){
IsInitialVoiceFinshed = false;
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if(result.get(0).contains("cancel"))
{
tts.speak("Transaction Cancelled!",TextToSpeech.QUEUE_FLUSH,null);
}
else {
switch (numberOfClicks) {
case 1:
To1.setText("");
String ifsc;
ifsc = result.get(0).replace(" ","");
char[] str=ifsc.toCharArray();
for(int i=0;i< str.length;i++){
To1.append(str[i]+"");
Toast.makeText(getApplicationContext(), To1.getText().toString(), Toast.LENGTH_SHORT).show();
}
if(!To1.getText().toString().isEmpty()) {
tts.speak("tap on the screen & say, account number to whom you want to transfer money? ",TextToSpeech.QUEUE_FLUSH,null);
}
break;
case 2:
to = result.get(0).replaceAll("[^\\d.]", "");
To.setText(to);
if(!to.isEmpty()) {
tts.speak("tap on the screen & say, how much money you want to transfer",TextToSpeech.QUEUE_FLUSH,null);
}
break;
case 3:
String amount;
amount = result.get(0).replaceAll("[^\\d.]", "");
Subject.setText(amount);
status.setText("confirm");
if(!amount.isEmpty()) {
tts.speak("Please Confirm the details , IFSC code is "+To1.getText().toString()+",Account number is: " + Arrays.toString(To.getText().toString().split("(?!^)")) + ". And Money that you want to transfer is ,: " + Subject.getText().toString() +"rupees"+ ",Tap on the screen and Speak Yes to confirm",TextToSpeech.QUEUE_FLUSH,null);
tts.speak(",swipe left to listen again, or say Yes to confirm or no to cancel the transaction",TextToSpeech.QUEUE_ADD,null);
}
break;
default:
if(result.get(0).equals("yes")) {
if (To.getText().toString().equals("")) {
if (Subject.getText().toString().equals("")) {
tts.speak("Details may be incorrect or incomplete, canceling the transaction",TextToSpeech.QUEUE_FLUSH,null);
final Handler h = new Handler(Looper.getMainLooper());
h.postDelayed(new Runnable() {
#Override
public void run() {
Intent i = new Intent(Banktransfer.this,MainActivity.class);
startActivity(i);
}
},8000);
}
} else {
status.setText("transferring money ");
tts.speak("transferring money please wait",TextToSpeech.QUEUE_FLUSH,null);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
status.setText("Amount transferred successfully.");
tts.speak("Amount transferred successfully.",TextToSpeech.QUEUE_FLUSH,null);
}
}, 6000);
final Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
finish();
Intent intent = new Intent(Banktransfer.this, MainActivity.class);
startActivity(intent);
tts.speak("you are in main menu. just swipe right and say what you want", TextToSpeech.QUEUE_FLUSH, null);
}
}, 9000);
}
}
else if(result.get(0).contains("no")){
tts.speak("transaction cancelled",TextToSpeech.QUEUE_FLUSH,null);
To.setText("");
Subject.setText("");
IsInitialVoiceFinshed=true;
final Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
finish();
Intent intent = new Intent(Banktransfer.this,MainActivity.class);
startActivity(intent);
}
},3000);
}
}
}
}
else {
switch (numberOfClicks) {
case 1:
break;
case 2:
break;
default:
tts.speak("say yes to proceed the transaction or no to cancel the transaction",TextToSpeech.QUEUE_FLUSH,null);
break;
}
numberOfClicks--;
}
}
IsInitialVoiceFinshed=true;
}
public boolean onTouchEvent(MotionEvent touchEvent) {
switch (touchEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = touchEvent.getX();
break;
case MotionEvent.ACTION_UP:
x2 = touchEvent.getX();
if (x1 < x2) {
tts.speak("Please Confirm the details , IFSC code is "+To1.getText().toString()+"Account number is: " + Arrays.toString(To.getText().toString().split("(?!^)")) + ". And Money that you want to transfer is ,: " + Subject.getText().toString() +"rupees"+ ",Tap on the screen and Speak Yes to confirm",TextToSpeech.QUEUE_FLUSH,null);
tts.speak("swipe left to listen again, and say Yes to confirm or no to cancel the transaction",TextToSpeech.QUEUE_ADD,null);
break;
}
if (x1 > x2) {
break;
}
break;
}
return false;
}
public void onPause() {
if (tts != null) {
tts.stop();
}
super.onPause();
}
}
bank_transfer.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#faa519"
android:orientation="vertical"
android:onClick = "layoutClicked"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="48dp"
android:background="#e8e8e7"
android:orientation="horizontal">
<TextView
android:id="#+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_marginLeft="25dp"
android:text="Bank transfer"
android:textColor="#2582C5"
android:textSize="18sp"
android:textStyle="bold" />
</RelativeLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="30dp"
android:orientation="vertical">
<ImageView
android:layout_width="161dp"
android:layout_height="77dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="15dp"
android:src="#drawable/bank" />
<TextView
android:id="#+id/to1"
android:layout_width="fill_parent"
android:layout_height="85dp"
android:layout_marginTop="70dp"
android:background="#f3f3f3"
android:paddingLeft="7dp"
android:paddingTop="7dp"
android:text="IFSC Code"
android:textColor="#4C4D4F" />
<TextView
android:id="#+id/to"
android:layout_width="fill_parent"
android:layout_height="85dp"
android:layout_marginTop="80dp"
android:background="#f3f3f3"
android:paddingLeft="7dp"
android:paddingTop="7dp"
android:text="Acc. no"
android:textColor="#4C4D4F" />
<TextView
android:id="#+id/subject"
android:layout_width="fill_parent"
android:layout_height="95dp"
android:layout_marginTop="95dp"
android:background="#f3f3f3"
android:text="Transfer money:- "
android:textColor="#4C4D4F" />
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
Instead of using switch statement You can use the codes below:
if(//){
}else if(//){
}else if(//){
}else if(//){
}else{
//
}
but switch statement, it's simpler and readable than the if and else if
In my app, I have integrated Mapbox and It was working fine. But now It's not loading a map in NavigationView. It is working fine in master branch but not working on the BLE features branch even though I have not changed anything in that Activity. Please find below code here, I am launching this NavigationActivity from MainActivity where user select origin and destination locations.
NavigationActivity-Screen:
NavigationActivity.java:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.mapbox.api.directions.v5.models.BannerText;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.api.directions.v5.models.LegStep;
import com.mapbox.services.android.navigation.ui.v5.NavigationViewOptions;
import com.mapbox.services.android.navigation.ui.v5.OnNavigationReadyCallback;
import com.mapbox.services.android.navigation.ui.v5.instruction.InstructionLoader;
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
import com.mapbox.services.android.navigation.v5.milestone.Milestone;
import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener;
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
import java.math.BigDecimal;
import java.util.List;
public class NavigationActivity extends AppCompatActivity implements MilestoneEventListener, OnNavigationReadyCallback {
private TextView myBanner;
ImageView next, previous;
List<LegStep> steps;
TextView tv_step;
int currentStepIndex = 0;
DirectionsRoute currentRoute = null ;
com.mapbox.services.android.navigation.ui.v5.NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigations);
navigationView = findViewById(R.id.navigationView);
myBanner = findViewById(R.id.dummyBanner);
tv_step = findViewById(R.id.tv_step);
next = findViewById(R.id.iv_next);
previous = findViewById(R.id.iv_previous);
navigationView.onCreate(savedInstanceState);
navigationView.initialize(this);
try{
currentRoute = (DirectionsRoute) getIntent().getSerializableExtra("route");
if(currentRoute != null){
steps = currentRoute.legs().get(0).steps();
if(steps.size() > 0){
setup();
}
}
}catch (Exception e){}
}
private void setup(){
loadText( 0);
next.setOnClickListener((View v )-> {
if (currentStepIndex < steps.size() - 2)
loadText(++currentStepIndex);
});
previous.setOnClickListener((View v )-> {
if (currentStepIndex > 0)
loadText(--currentStepIndex);
});
}
private void loadText( int index){
BannerText bannerText = steps.get(index).bannerInstructions().get(0).primary();
InstructionLoader loader = new InstructionLoader(tv_step, bannerText );
loader.loadInstruction();
String text = tv_step.getText().toString();
String modifier = bannerText.modifier();
String directionArrow = getDirectionArrow(text, modifier);
if(!directionArrow.equals(""))
tv_step.setText(directionArrow + text);
tv_step.append(" " + getDistanceStr(steps.get(index).distance()));
Log.d("Debugging modifier", bannerText.toJson());
}
#Override
public void onNavigationReady(boolean isRunning) {
DirectionsRoute directionsRoute = (DirectionsRoute) getIntent().getSerializableExtra("route");
NavigationViewOptions options = NavigationViewOptions.builder()
.directionsRoute(directionsRoute)
.shouldSimulateRoute(false)
.milestoneEventListener(this)
.build();
navigationView.startNavigation(options);
}
#Override
public void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
try {
if (milestone instanceof BannerInstructionMilestone) {
BannerText primaryInstruction = ((BannerInstructionMilestone) milestone).getBannerInstructions().primary();
primaryInstruction.text();
InstructionLoader loader = new InstructionLoader(myBanner, primaryInstruction);
loader.loadInstruction();
String text = myBanner.getText().toString();
String modifier = primaryInstruction.modifier();
String directionArrow = getDirectionArrow(text, modifier);
if(!directionArrow.equals(""))
myBanner.setText(directionArrow + text);
double distance = routeProgress.currentLegProgress().currentStep().distance();
String distanceStr = getDistanceStr(distance);
String milestoneString = myBanner.getText().toString() + distanceStr;
}
}catch (Exception e){
e.printStackTrace();
}
}
private String getDirectionArrow(String text, String modifier){
Log.e("Debugging", text + " " + modifier);
if (text.contains("right") || modifier.contains("right"))
return "> ";
else if (text.contains("left") || modifier.contains("left"))
return "< ";
else if (text.contains("straight") || modifier.contains("straight"))
return "^ ";
return "";
}
private String getDistanceStr(double distance){
if(distance > 1000)
return " " + formatAmount(distance/1000) + " km";
else return " " + distance + " m";
}
#Override
public void onStart() {
super.onStart();
navigationView.onStart();
}
#Override
public void onResume() {
super.onResume();
navigationView.onResume();
}
#Override
public void onLowMemory() {
super.onLowMemory();
navigationView.onLowMemory();
}
#Override
public void onBackPressed() {
if (!navigationView.onBackPressed()) {
super.onBackPressed();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
navigationView.onSaveInstanceState(outState);
super.onSaveInstanceState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
navigationView.onRestoreInstanceState(savedInstanceState);
}
#Override
public void onPause() {
super.onPause();
navigationView.onPause();
}
#Override
public void onStop() {
super.onStop();
navigationView.onStop();
}
#Override
protected void onDestroy() {
super.onDestroy();
navigationView.onDestroy();
}
public static String formatAmount(Double str){
BigDecimal bd = new BigDecimal(str);
bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
return bd.toString();
}
}
activity_navigations.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="talha.niazi.hudlitenav.MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:id="#+id/dummyBanner"
android:background="#color/design_default_color_primary"
android:textColor="#color/mapboxWhite"
android:padding="10dp"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:background="#color/button_red"
android:id="#+id/ll_nav"
android:padding="15dp"
android:layout_height="wrap_content">
<ImageView
android:layout_width="30sp"
android:tint="#color/white_color"
android:id="#+id/iv_previous"
mapbox:srcCompat="#drawable/previous"
android:layout_height="30sp" />
<TextView
android:layout_width="wrap_content"
android:textColor="#color/white_color"
android:layout_marginStart="10sp"
android:textStyle="bold"
android:layout_marginEnd="10sp"
android:layout_centerVertical="true"
android:id="#+id/tv_step"
android:layout_centerHorizontal="true"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="30sp"
android:layout_alignParentEnd="true"
android:id="#+id/iv_next"
android:tint="#color/white_color"
mapbox:srcCompat="#drawable/next"
android:layout_height="30sp" />
</RelativeLayout>
<com.mapbox.services.android.navigation.ui.v5.NavigationView
android:id="#+id/navigationView"
android:layout_below="#id/ll_nav"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
It would be great if you can help me to fix this weird issue.
Can you try to set the content theme
super.onCreate(savedInstanceState)
setTheme(R.style.Theme_AppCompat_Light_NoActionBar);
before setting the contentView?
Also where did you set the style of NavigationView? You can do that in the layout XML file:
<com.mapbox.services.android.navigation.ui.v5.NavigationView
android:id="#+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navigationDarkTheme="#style/CustomNavigationView"
app:navigationLightTheme="#style/CustomNavigationView"
app:navigationViewMapStyle="mapbox://styles/StyleURL"/>
Please use your custom styleURL.
Please let me know if it helped!
Solution in Kotlin
For more information
This issue has been resolved here Can’t start turn-by-turn navigation within custom NavigationViewActivity/NavigationViewFragment #1524
First I updated the SDK version from 0.13.0 to 0.23.0
implementation 'com.mapbox.mapboxsdk:mapbox-android-navigation-ui:0.23.0'
The dependency will transitively bring in the Maps SDK and the core navigation libraries. This helps prevents conflicts.
In project root build.gradle don't forget to add
maven { url 'https://mapbox.bintray.com/mapbox' }
in fragment_navigation.xml
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="NavigationViewFragment">
<com.mapbox.navigation.ui.NavigationView
android:id="#+id/navigationView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
In NavigationViewFragment
originPoint and destinationPoint is variable type Point.fromLngLat(longitude,latitude)
class NavigationViewFragment : Fragment(), OnNavigationReadyCallback, NavigationListener {
private lateinit var navigationView: NavigationView
var directionsRoute: DirectionsRoute? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
.....
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navigationView = view.findViewById(R.id.navigationView) as NavigationView
navigationView.onCreate(savedInstanceState)
val initialPosition = CameraPosition.Builder()
.target(LatLng(originPoint.longitude(), originPoint.latitude()))
.zoom(18.0)
.build()
navigationView.initialize(this, initialPosition)
}
override fun onNavigationReady(isRunning: Boolean) {
val origin = Point.fromLngLat(originPoint.longitude() , originPoint.latitude())
val destination = Point.fromLngLat(destinationPoint.longitude(), destinationPoint.latitude())
calculateRoute(origin, destination)
}
override fun onCancelNavigation() {
// Do something
}
override fun onNavigationFinished() {
// Do something
}
override fun onNavigationRunning() {
// Do something
}
private fun calculateRoute(origin: Point , destination: Point) {
NavigationRoute.builder(this.context)
.accessToken(Mapbox.getAccessToken()!!)
.origin(origin)
.destination(destination)
.build()
.getRoute( object : Callback<DirectionsResponse> { //import retrofit2.Callback
// Send request to Direction API
override fun onFailure(call: Call<DirectionsResponse>? , t: Throwable?) {
}
override fun onResponse(call: Call<DirectionsResponse>? ,
response: Response<DirectionsResponse>?) {
if (response?.body() == null || response.body()?.routes()?.size!! < 1) {
return
}
directionsRoute = response.body()!!.routes()[0]
startNavigation()
}
})
}
private fun startNavigation() {
if (directionsRoute == null) return
val options = NavigationViewOptions.builder()
.directionsRoute(directionsRoute)
.shouldSimulateRoute(true)
.navigationListener(this)
.build()
// start camera zooms to the beginning of the route
navigationView.startCamera(directionsRoute)
navigationView.startNavigation(options)
}
}
I'm working on a small project where a user is shown his result after he tries to login and he already taken the quiz on my app.
So i'm using a page like this to display result.
But i cannot display my score. This page also has an option to share your score which is working fine and displaying score.Share option containing result.
I'm attaching my XML and Java Code kindly please help me solve the issue that'll be great help.
Thanks & Regards
BugAdder
XML Code:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center|top">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:padding="20dp"
android:textAlignment="center"
android:textSize="25sp"
android:textStyle="bold"
android:text="#string/login_score_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:padding="20dp"
android:textSize="25sp"
android:textStyle="bold"
android:text="#string/score_result"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:textStyle="bold"
android:id="#+id/login_score_text"/>
<Button
android:padding="20dp"
android:layout_marginTop="75dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/login_share_button"
android:text="#string/share_button"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="#string/exit_button"
android:drawableEnd="#drawable/arrow_right"
android:drawableRight="#drawable/arrow_right"
android:id="#+id/login_exit_button"/>
</LinearLayout>
</ScrollView>
Java Code:
public class QuizLoginScore extends AppCompatActivity {
private List<ScoreItem> mScoreItems = new ArrayList<>();
private ProgressDialog mProgressDialog;
private String mScore;
private TextView mScoreTextView;
private Button mShareButton;
private Button mExitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_login_quiz);
mScoreTextView = (TextView)findViewById(R.id.login_score_text);
mShareButton = (Button)findViewById(R.id.login_share_button);
mExitButton = (Button)findViewById(R.id.login_exit_button);
new FetchScoresTask().execute();
mScoreTextView.setText(mScore);
mExitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >= 21){
finishAndRemoveTask();
}else{
finishAffinity();
System.exit(0);
}
}
});
mShareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT,getScoreShareReport(mScore));
i.putExtra(Intent.EXTRA_SUBJECT,getString(R.string.score_report_subject));
i = Intent.createChooser(i,getString(R.string.send_report));
startActivity(i);
}
});
}
public String getScoreShareReport(String score){
String result;
StringBuilder sb = new StringBuilder();
sb.append("QuizApp!").
append("\n\n").
append("I Just Scored").
append(" \' ").
append(score).
append(" \' ").
append("marks out of \' 100 \' in Latest Quiz on QuizApp!\nWhats your Score Huh?");
result = sb.toString();
return result;
}
private class FetchScoresTask extends AsyncTask<Void, Void, List<ScoreItem>> {
#Override
protected void onPreExecute() {
mProgressDialog = new ProgressDialog(QuizLoginScore.this);
mProgressDialog.setTitle("Downloading Score");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("Please wait while the score is being downloaded!");
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
#Override
protected List<ScoreItem> doInBackground(Void... params) {
return new ScoreFetcher().fetchScoreItems();
}
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
break;
}
}
mProgressDialog.dismiss();
}
}
}
mScore is set in a async task. so you must set text in onPostExecute. try following code:
public class QuizLoginScore extends AppCompatActivity {
private List<ScoreItem> mScoreItems = new ArrayList<>();
private ProgressDialog mProgressDialog;
private String mScore;
private TextView mScoreTextView;
private Button mShareButton;
private Button mExitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score_login_quiz);
mScoreTextView = (TextView)findViewById(R.id.login_score_text);
mShareButton = (Button)findViewById(R.id.login_share_button);
mExitButton = (Button)findViewById(R.id.login_exit_button);
new FetchScoresTask().execute();
mScoreTextView.setText(mScore);
mExitButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(Build.VERSION.SDK_INT >= 21){
finishAndRemoveTask();
}else{
finishAffinity();
System.exit(0);
}
}
});
mShareButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_TEXT,getScoreShareReport(mScore));
i.putExtra(Intent.EXTRA_SUBJECT,getString(R.string.score_report_subject));
i = Intent.createChooser(i,getString(R.string.send_report));
startActivity(i);
}
});
}
public String getScoreShareReport(String score){
String result;
StringBuilder sb = new StringBuilder();
sb.append("QuizApp!").
append("\n\n").
append("I Just Scored").
append(" \' ").
append(score).
append(" \' ").
append("marks out of \' 100 \' in Latest Quiz on QuizApp!\nWhats your Score Huh?");
result = sb.toString();
return result;
}
private class FetchScoresTask extends AsyncTask<Void, Void, List<ScoreItem>> {
#Override
protected void onPreExecute() {
mProgressDialog = new ProgressDialog(QuizLoginScore.this);
mProgressDialog.setTitle("Downloading Score");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setMessage("Please wait while the score is being downloaded!");
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
#Override
protected List<ScoreItem> doInBackground(Void... params) {
return new ScoreFetcher().fetchScoreItems();
}
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
mScoreTextView.setText(mScore);
break;
}
}
mProgressDialog.dismiss();
}
}
}
Put your mScore string in log to see if you are getting the data in logcat. Also try changing the color of your textview. Also put your textview.settext() in onpostexecute(); method
Set text from onPostExecute():
#Override
protected void onPostExecute(List<ScoreItem> scoreItems) {
mScoreItems = scoreItems;
for(int i = 0; i < mScoreItems.size(); i++){
if(mScoreItems.get(i).getUserId().equals(QuizLogin.mUserIdString)){
mScore = String.valueOf(mScoreItems.get(i).getScore());
mScoreTextView.setText(mScore);
break;
}
}
mProgressDialog.dismiss();
}
My application keeps on crashing, and I cannot figure out why. I am suspecting that there is something wrong with the getReactants() method because the button is working just fine and can display any other text I put in the beq.setText().
There are no errors in the logcat, the threads are simply suspended and my device says that the application is not responding, and says I can either wait or kill the app.
Here is my code.
Java
package me.finalproject.com.apchemchemolyapp;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
import java.io.Serializable;
/**
* Created by Shishir on 6/9/2016.
*/
public class stoich_fragment extends Fragment implements View.OnClickListener, Serializable
{
View rootview;
int i = 0;
ArrayList<Integer> arr = new ArrayList<>();
ArrayList<String> elements = new ArrayList<>();
boolean getElements = true;
String s1;
String element = "";
EditText reactants;
TextView beq;
Button go;
int temp;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
rootview = inflater.inflate(R.layout.stoich_layout, container, false);
reactants = (EditText) rootview.findViewById(R.id.reactants);
go = (Button) rootview.findViewById(R.id.button);
go.setOnClickListener(this);
return rootview;
}
public void onClick(View v)
{
getReactants(s1);
beq = (TextView) rootview.findViewById(R.id.balanced_equation);
beq.setText(s1);
}
public void getReactants(String s)
{
String reactant = reactants.getText().toString();
//saying that reactants is null even after it went through the onCreateView method
String re = reactant.replaceAll("\\s+","");
while(getElements)
{
String let = re.substring(i, i+1);
if(let.compareTo(let.toLowerCase()) > 0)
{
element += let;
if(i == re.length()-1 || i == re.length())
{
elements.add(element);
if(re.substring(re.length()-1).equals("2")||re.substring(re.length()-1).equals("3")||re.substring(re.length()-1).equals("4")||re.substring(re.length()-1).equals("5")||re.substring(re.length()-1).equals("6")||re.substring(re.length()-1).equals("7")||re.substring(re.length()-1).equals("8")||re.substring(re.length()-1).equals("9"))
{
arr.add(Integer.parseInt(re.substring(re.length()-1)));
}
else
{
arr.add(1);
elements.add(re.substring(re.length()-1));
arr.add(1);
}
getElements = false;
}
else if(re.substring(i+1, i+2).compareTo(re.substring(i+1, i+2).toLowerCase()) != 0)
{
if(!re.substring(i+1,i+2).equals("2")||!re.substring(i+1,i+2).equals("3")||!re.substring(i+1,i+2).equals("4")||!re.substring(i+1,i+2).equals("5")||!re.substring(i+1,i+2).equals("6")||!re.substring(i+1,i+2).equals("7")||!re.substring(i+1,i+2).equals("8")||!re.substring(i+1,i+2).equals("9"))
{
temp = 1;
arr.add(temp);
}
}
}
else if(let.compareTo(let.toLowerCase()) == 0)
{
element += let;
if(i == re.length()-1 || i == re.length())
{
elements.add(element);
if(re.substring(re.length()-1).equals("2")||re.substring(re.length()-1).equals("3")||re.substring(re.length()-1).equals("4")||re.substring(re.length()-1).equals("5")||re.substring(re.length()-1).equals("6")||re.substring(re.length()-1).equals("7")||re.substring(re.length()-1).equals("8")||re.substring(re.length()-1).equals("9"))
{
arr.add(Integer.parseInt(re.substring(re.length()-1)));
}
else
{
arr.add(1);
elements.add(re.substring(re.length()-1));
arr.add(1);
}
getElements = false;
}
else if(!re.substring(i+1,i+2).equals("2")||re.substring(i+1,i+2).equals("3")||re.substring(i+1,i+2).equals("4")||re.substring(i+1,i+2).equals("5")||re.substring(i+1,i+2).equals("6")||re.substring(i+1,i+2).equals("7")||re.substring(i+1,i+2).equals("8")||re.substring(i+1,i+2).equals("9"))
{
temp = 1;
arr.add(temp);
}
}
else if (let.equals("2")||let.equals("3")||let.equals("4")||let.equals("5")||let.equals("6")||let.equals("7")||let.equals("8")||let.equals("9"))
{
temp = Integer.parseInt(let);
arr.add(temp);
elements.add(element);
element = "";
}
i++;
if(i == re.length()+1)
{
getElements = false;
}
}
// displays the elements isolated on the reactant side
// to test to make sure my logic works
for(int a = 0; a<elements.size(); a++)
{
s += (elements.get(a) + " : " + arr.get(a) + "\n");
}
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/reactants"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="95dp"
android:textSize="20sp"
android:inputType="text" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/products"
android:layout_alignBottom="#+id/reactants"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:textSize="20sp"
android:inputType="text" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/balanced_equation"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:textSize="30sp" />
<!--should make text bold and black-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/beq"
android:id="#+id/title"
android:textSize="35sp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textStyle = "bold"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/button"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="45dp" />
</RelativeLayout>
This messages means your application is doing too much work on it's main thread (UI Tread).
I suggest to put getReactants() in an AsyncTask and show the result when all proccesses finished without blocking the main thread.
Looking at your code, it seems that you probably have an infinite loop. Try to set your getElements flag to false at the end of your while loop to make sure it will be executed. Must be something like:
while(getElements)
{
String let = re.substring(i, i+1);
if(let.compareTo(let.toLowerCase()) > 0)
{
element += let;
if(re.substring(i+1, i+2).compareTo(re.substring(i+1, i+2).toLowerCase()) != 0)
{
if(!re.substring(i+1,i+2).equals("2")||re.substring(i+1,i+2).equals("3")||re.substring(i+1,i+2).equals("4")||re.substring(i+1,i+2).equals("5")||re.substring(i+1,i+2).equals("6")||re.substring(i+1,i+2).equals("7")||re.substring(i+1,i+2).equals("8")||re.substring(i+1,i+2).equals("9"))
{
temp = 1;
arr.add(temp);
}
}
i++;
}
else if(let.compareTo(let.toLowerCase()) == 0)
{
element += let;
if(!re.substring(i+1,i+2).equals("2")||re.substring(i+1,i+2).equals("3")||re.substring(i+1,i+2).equals("4")||re.substring(i+1,i+2).equals("5")||re.substring(i+1,i+2).equals("6")||re.substring(i+1,i+2).equals("7")||re.substring(i+1,i+2).equals("8")||re.substring(i+1,i+2).equals("9"))
{
temp = 1;
arr.add(temp);
}
i++;
}
else if (let.equals("2")||let.equals("3")||let.equals("4")||let.equals("5")||let.equals("6")||let.equals("7")||let.equals("8")||let.equals("9"))
{
temp = Integer.parseInt(let);
arr.add(temp);
elements.add(element);
element = "";
}
if(i == re.length())
{
getElements = false;
}
// must have an else statement here or else you will have an infinite loop if your condition is always false.
}
You are not incrementing i in some cases, you should have to move i++ to the end of your while to avoid an infinite loop
i has to be incremented in all cases, consider something like this:
if () {
`enter code here`
}
else if () {
`enter code here`
}
else if () {
`enter code here`
}
i++;
if(i == re.length()) {
getElements = false;
}
So, I have scoured the interwebs and I cannot find a solution for this based on other people's experiences, so I am posting this issue. (Please note that this is my 1st android app experience and I am debugging / updating an existing app.)
When I implement my custom NotesListAdapter (extends BaseAdapter) on the ListView, mListNotesView (mListNotesView.setAdapter(this)), and load the data into the ArrayList mNoteList, the getView function is not being called. Also, I found that mListNotesView.setBackgroundResource is not chaning the background of the control, either. I have a similar implementation on a previous activity that works exactly correct. When I copied over the class and changed it to handle my ArrayList, it broke. I have getCount returning the ArrayList size(), which is not 0, and getItemId returns position. I have a feeling it may be my XML or my setup because it's acting like the ListView is not visible. I am perplexed. How do I get the ListView to show? Anything inside of the getView has not been reached so it may be buggy.
ViewTicketOrderActivity (Some parts ommitted for size)
public class ViewTicketOrderActivity extends Activity {
MySQLDatabase myDataBase;
Ticket mTicket;
public ArrayList<Notes> mNotes = new ArrayList<Notes>();
String mErrorString;
Button mAddUpdateButton;
Button mAcceptButton;
//Button mViewNotesButton;
NotesListAdapter mNotesListAdapter;
static final int ERROR_DIALOG = 0;
static final int SUCCESS_DIALOG = 1;
static final int COMPLETED_DIALOG = 2;
static final int RESTART_DIALOG = 3;
static final int LOADING = 0;
static final int LOAD_ERROR = 1;
static final int LOADED = 4;
static final String TICKET_EXTRA = "ticket_extra";
static final String TAG = "ViewTicketOrderActivity";
private static final boolean gDebugLog = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewticketorder);
Activity context = this;
String theTitle = "Sundance Ticket Order";
theTitle += (MySQLDatabase.TESTING == true) ? " (DEV SERVER)" : " (LIVE)";
setTitle(theTitle);
myDataBase = MySQLDatabase.getMySQLDatabase(this);
if (gDebugLog) {
DebugLogger.logString(TAG, ".onCreate");
}
mNotesListAdapter = new NotesListAdapter(context, R.id.note_list);
Log.d(this.toString(),this.mNotesListAdapter.toString());
}
private class NotesListAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private ArrayList<Notes> mNoteList;
private ListView mListNotesView;
private Activity mActivity;
int mState = LOADING;
String mErrorMessage;
private NotesListAdapter(Activity context, int listViewID) {
mActivity = context;
mNoteList = new ArrayList<Notes>();
mInflater = LayoutInflater.from(context);
mListNotesView = (ListView)context.findViewById(listViewID);
mListNotesView.setBackgroundResource(R.color.emergency_red);
mListNotesView.setAdapter(this);
Log.d(mListNotesView.toString(), String.valueOf(mListNotesView.getCount()));
this.notifyDataSetChanged();
//mListNotesView.setVisibility(View.VISIBLE);
}
void setLoading()
{
mState = LOADING;
this.notifyDataSetChanged();
}
void setLoadError(String errorString)
{
mState = LOAD_ERROR;
mErrorMessage = errorString;
this.notifyDataSetChanged();
}
void setNoteList(ArrayList<Notes> inNotes)
{
mState = LOADED;
mNoteList.clear();
mNoteList.addAll(inNotes);
Log.d("SetNoteList", "TRUE " + inNotes);
//mNoteList = mNotes;
this.notifyDataSetChanged();
}
/**
* Use the array index as a unique id.
*
* #see android.widget.ListAdapter#getItemId(int)
*/
#Override
public long getItemId(int position) {
return position;
}
public int getCount(){
if (mState == LOADED) {
Log.d("getCount",String.valueOf(mNoteList.size()));
return mNoteList.size();
} else {
return 0;
}
}
/**
* Make a view to hold each row.
*
* #see android.widget.ListAdapter#getView(int, android.view.View,
* android.view.ViewGroup)
*/
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
Log.d("getView",this.toString());
if (mState == LOADED) {
ViewHolder holder;
// When convertView is not null, we can reuse it directly, there
// is no need
// to reinflate it. We only inflate a new View when the
// convertView supplied
// by ListView is null.
Notes note = this.getItem(position);
if (convertView == null) {
/*if (ticket.emergency())
{
convertView = mInflater.inflate(R.layout.emergency_ticket_list_item_opt,
null);
}
else
{
convertView = mInflater.inflate(R.layout.ticket_list_item,
null);
}*/
convertView = mInflater.inflate(R.layout.noteslist_item,
null);
// Creates a ViewHolder and store references to the two
// children views
// we want to bind data to.
holder = new ViewHolder();
holder.noteText = (TextView) convertView
.findViewById(R.id.text_note);
holder.dateText = (TextView) convertView
.findViewById(R.id.text_note_date);
holder.createByText = (TextView) convertView
.findViewById(R.id.text_note_by);
holder.createByIDText = (TextView) convertView
.findViewById(R.id.text_note_by_id);
convertView.setTag(holder);
} else {
// Get the ViewHolder back to get fast access to the
// TextView
// and the ImageView.
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.noteText.setText(note.note());
holder.dateText.setText(note.date());
holder.createByText.setText(note.createBy());
holder.createByIDText.setText(note.employeeID());
if(!mTicket.employeeID().equals(note.employeeID())){
convertView.setBackgroundResource(R.drawable.solid_purple);
}
} else if (mState == LOADING ) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.loading_view,
null);
}
TextView messageText = (TextView)convertView.findViewById(R.id.message);
messageText.setText("Loading tickets");
} else if (mState == LOAD_ERROR) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.load_error_view,
null);
}
TextView messageText = (TextView)convertView.findViewById(R.id.message);
messageText.setText("Error loading tickets");
String errorString = mErrorMessage != null ? mErrorMessage : "";
TextView errorText = (TextView)convertView.findViewById(R.id.errorText);
errorText.setText(errorString);
}
return convertView;
}
class ViewHolder {
TextView noteText;
TextView dateText;
TextView createByText;
TextView createByIDText;
}
//#Override
/*public int getCount() {
*//*if (mState == LOADED) {
*//*
Log.d("getCount mState " + mState,String.valueOf(mNoteList.size())+", "+String.valueOf(mNotes.size()));
return mNoteList.size();
*//*} else {
Log.d("getCount mState " + mState,"0");
return 0;
}*//*
}*/
#Override
public Notes getItem(int position) {
Log.d("getItem",mNoteList.get(position).toString());
return mNoteList.get(position);
}
#Override
public int getItemViewType (int position) {
int result = mState;
Log.d("getItemId",String.valueOf(position));
return result;
}
#Override
public int getViewTypeCount ()
{
return 4;
}
}
protected void onResume() {
super.onResume();
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
mTicket = (Ticket)extras.getSerializable(TICKET_EXTRA);
}
else
{
mTicket = new Ticket();
}
if (mTicket.emergency())
{
setContentView(R.layout.view_emergency_ticketorder);
}
else
{
setContentView(R.layout.viewticketorder);
}
if (gDebugLog)
{
DebugLogger.logString(TAG, ".onResume mTicket " + mTicket);
}
TicketCheckService.clearNotificationForNewTicket(mTicket);
new GetTicketTask().execute();
new GetNotesTask().execute();
updateDisplayedTicket();
}
private void updateDisplayedTicket() {
mAddUpdateButton = (Button)findViewById(R.id.addUpdateButton);
mAcceptButton = (Button)findViewById(R.id.acceptButton);
//mViewNotesButton = (Button)findViewById(R.id.viewNotesButton);
String ticketStatus = myDataBase.getDescriptionStringForStatusString(mTicket.status());
if(ticketStatus == "Job Rejected") {
mAddUpdateButton.setText("Restart Job");
} else {
mAddUpdateButton.setText("Add Update");
}
if(ticketStatus == "Requested") {
mAcceptButton.setText("Accept");
} else if(ticketStatus != "Requested") {
mAcceptButton.setText("Back");
}
//mViewNotesButton.setText(R.string.viewNotes);
TextView idText = (TextView)findViewById(R.id.textTicketID);
idText.setText(mTicket.id());
//TextView descriptionText = (TextView)findViewById(R.id.textDescription);
//descriptionText.setText(mTicket.description());
TextView titleText = (TextView)findViewById(R.id.textTitle);
titleText.setText(mTicket.title());
TextView storeIDText = (TextView)findViewById(R.id.textStoreID);
storeIDText.setText(mTicket.store());
String formatPhone;
TextView storePhoneText = (TextView)findViewById(R.id.textStorePhone);
if(mTicket.phoneNo().isEmpty()){
formatPhone = "NO PHONE NO.";
} else {
storePhoneText = (TextView) findViewById(R.id.textStorePhone);
formatPhone = mTicket.phoneNo().replaceFirst("(\\d{3})(\\d{3})(\\d+)", "($1)$2-$3");
storePhoneText.setOnClickListener(new CallClickListener(mTicket.phoneNo()));
}
storePhoneText.setText(formatPhone);
TextView categoryText = (TextView)findViewById(R.id.textCategory);
String categoryDescription = MySQLDatabase.getDescriptionStringForCategoryString(mTicket.category());
categoryText.setText(categoryDescription);
if(ticketStatus == "Completed Pending") {
showDialog(COMPLETED_DIALOG);
}
}
public void onClickAccept(View v) {
try {
boolean maint = myDataBase.getSystemMaintStatus();
if(maint) {
setLoadError("The phone app is down for maintenance.");
return;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mAcceptButton.getText() =="Accept") {
mAddUpdateButton.setEnabled(false);
mAcceptButton.setEnabled(false);
new AcceptTicketTask().execute();
} else {
finish();
}
}
public void onClickAddUpdate(View v) {
try {
boolean maint = myDataBase.getSystemMaintStatus();
if(maint) {
setLoadError("The phone app is down for maintenance.");
return;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mAddUpdateButton.getText() =="Add Update") {
Intent i = new Intent(this, UpdateTicketActivity.class);
i.putExtra(UpdateTicketActivity.TICKET_EXTRA, mTicket);
startActivity(i);
} else if(mAddUpdateButton.getText() =="Restart Job") {
mAddUpdateButton.setEnabled(false);
mAcceptButton.setEnabled(false);
new RestartTicketTask().execute();
}
}
private class AcceptTicketTask extends AsyncTask<Void, Integer, String>
{
protected String doInBackground(Void... parent) {
mErrorString = null;
String result = null;
String updateTime = DateFormat.getDateTimeInstance().format(new Date(0));
try {
boolean success = myDataBase.updateTicket(mTicket.id(), mTicket.employeeID(), mTicket.description(), "1", updateTime, null);
if (!success)
{
result = "Could not update Ticket";
}
} catch (IOException e) {
// TODO Auto-generated catch block
result = "Could not update Ticket - " + e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String errorString) {
if (null != errorString) {
mErrorString = errorString;
showDialog(ERROR_DIALOG);
} else {
showDialog(SUCCESS_DIALOG);
mAcceptButton.setText("Back");
}
mAddUpdateButton.setEnabled(true);
mAcceptButton.setEnabled(true);
}
}
private class RestartTicketTask extends AsyncTask<Void, Integer, String>
{
protected String doInBackground(Void... parent) {
mErrorString = null;
String result = null;
String updateTime = DateFormat.getDateTimeInstance().format(new Date(0));
try {
boolean success = myDataBase.updateTicket(mTicket.id(), mTicket.employeeID(), mTicket.description(), "7", updateTime, null);
if (!success)
{
result = "Could not update Ticket";
}
} catch (IOException e) {
// TODO Auto-generated catch block
result = "Could not update Ticket - " + e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String errorString)
{
if (null != errorString) {
mErrorString = errorString;
showDialog(ERROR_DIALOG);
} else {
showDialog(RESTART_DIALOG);
mAcceptButton.setText("Done");
mAddUpdateButton.setText("Add Update");
}
mAddUpdateButton.setEnabled(true);
mAcceptButton.setEnabled(true);
}
}
private class GetTicketTask extends AsyncTask<Void, Integer, Ticket>
{
String mError = null;
protected Ticket doInBackground(Void... parent) {
Ticket result = null;
try {
result = myDataBase.getTicketWithID(mTicket.id(), mTicket.employeeID());
} catch (IOException e) {
// TODO Auto-generated catch block
mError = e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Ticket result)
{
if (null != result) {
mTicket = result;
} else {
setLoadError(mError);
}
}
}
private class GetNotesTask extends AsyncTask<Void, Integer, ArrayList<Notes>> {
String mError = null;
protected ArrayList<Notes> doInBackground(Void... parent) {
ArrayList<Notes> result = new ArrayList<Notes>();
try {
result = myDataBase.getTicketNotes(mTicket.id());
} catch (IOException e) {
// TODO Auto-generated catch block
myDataBase.debugLog("Error caught" + e);
mError = e.getLocalizedMessage();
e.printStackTrace();
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(ArrayList<Notes> result) {
if (null != result) {
Log.d("Result", result.toString());
mNotes = result;
} else {
Log.d("SetNoteList","FALSE");
mNotesListAdapter.setLoadError(mError);
}
}
}
private void updateDisplayedNotes(){
ArrayList<Notes> newNotes = mNotes;
if(newNotes != null) {
mNotesListAdapter.setNoteList(newNotes);
}
}
/*private class updateDisplayedNotes extends AsyncTask<Void, Integer, ArrayList<Notes>> {
public ArrayList<Notes> newNotes = new ArrayList<Notes>();
public updateDisplayedNotes(){
super();
Log.d(this.toString(), "Updating");
}
protected ArrayList<Notes> doInBackground(Void... parent) {
Log.d(this.toString(), "Background Task");
for (Notes note : mNotes) {
Log.d(this.toString(),note.toString());
if(note != null) {
Log.d(this.toString(), "Note Added");
newNotes.add(note);
}
}
return newNotes;
}
protected void onPostExecute(ArrayList<Notes> newNotes)
{
if(newNotes != null) {
mNotes.clear();
mNotes.addAll(newNotes);
mNotesListAdapter.setNoteList(mNotes);
}
}
}*/
void setLoadError(String error) {
setContentView(R.layout.load_error_view);
TextView messageText = (TextView)findViewById(R.id.message);
messageText.setText("Error loading ticket");
String errorString = error != null ? error : "";
TextView errorText = (TextView)findViewById(R.id.errorText);
errorText.setText(errorString);
finish();
}
}
viewticketorder.xml (where note_list is)
<?xml version="1.0" encoding="utf-8"?>
<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:background="#drawable/background"
android:orientation="vertical"
tools:context=".ViewTicketOrderActivity"
tools:ignore="HardcodedText" >
<TextView
android:id="#+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:text="#string/loadingTicket"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/white_color"
android:textSize="20dp"
android:textIsSelectable="true"
android:background="#drawable/title_transparent_bg"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:paddingTop="2dp"
android:paddingLeft="10dp"
android:text="#string/ticketID"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/textTicketID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="#color/white_color"
android:textIsSelectable="true"/>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="3dp"
android:paddingTop="2dp"
android:text="#string/storeID"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:ignore="HardcodedText" />
<TextView
android:id="#+id/textStoreID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="#color/white_color"
android:textIsSelectable="true"/>
<TextView
android:id="#+id/textStorePhone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="true"
android:textColor="#color/white_color"
android:textIsSelectable="true"
/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/TextView05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:paddingTop="2dp"
android:text="#string/category"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/textCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center_vertical"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/white_color"
android:focusable="true"
android:textIsSelectable="true"/>
</LinearLayout>
<ListView
android:id="#+id/note_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5"
android:divider="#drawable/ticket_item_divider"
android:dividerHeight="1dp"
tools:ignore="NestedWeights"
android:choiceMode="singleChoice"
android:clickable="true"
android:background="#drawable/title_transparent_bg">
</ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="#+id/acceptButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:onClick="onClickAccept" />
<Button
android:id="#+id/addUpdateButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:onClick="onClickAddUpdate" />
</LinearLayout>
</LinearLayout>
notelist_item.xml (inflator)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text_note_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#80FFFFFF"
android:orientation="vertical"
>
<TextView
android:id="#+id/text_note"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="#string/filler_string"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/text_item_color"
android:textSize="#dimen/big_text_item_size" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight=".70"
>
<TextView
android:id="#+id/text_note_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="#string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/text_sub_item_color" />
<TextView
android:id="#+id/text_note_by"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="#string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/text_sub_item_color" />
<TextView
android:id="#+id/text_note_by_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="#string/filler_string"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#color/text_sub_item_color" />
</LinearLayout>
</LinearLayout>
I'm going to recommend you reorganize your code. Here are some general tips:
1) Keep your views like ListView in the Activity class. Don't try to inflate the view in your adapter class. So in your activity's onCreate() after setContentView() you should have something like:
ListView listView = (ListView) findViewById(R.id.listView);
2) Next you need to get the data that will be shown in the listview and store it in a list. I didn't see in your code where the data comes from, but let's just say it comes from a database. You should create something like an ArrayList and store the data that you want to show in the ListView in the ArrayList
3) Next you need to create an adapter and pass the list of data into the adapter.
4) Once this has been done the ListView now has an adapter that will supply data to it. If you've done everything correctly then the system will eventually call getView() automatically and your code inside that should run and render the view.
Not an exact solution, but hopefully this explanation will help you figure it out.