Change Textview based on String - java

I'm trying to change the text in TextView based on the string of the previous view with a Listview.
For some reason, it keeps returning an error. Here's my code:
public class LyricsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/** Inflating the layout country_details_fragment_layout to the view object v */
View v = inflater.inflate(R.layout.learnlyrics, null);
/** Getting the textview object of the layout to set the details */
TextView tv = (TextView) v.findViewById(R.id.learnsong);
Bundle b = getArguments();
tv.setText("Details of " + Country.name[b.getInt("position")]);
int position = b.getInt("position");
String s = b.getInt("position");
if (s.startsWith("Pretty Hurts")) {
tv.setText("[Intro]\\nHarvey Keitel: Ms. Third Ward, your first question -- what is your aspiration in life?\\n" +
"Beyoncé: Oh, my aspiration in life would be to be happy\\n\\n[Verse 1]\\nMama said, you're a pretty girl\\n " +
"What's in your head it doesn't matter\\nBrush your hair, fix your teeth\\nWhat you wear is all that matters\\n\\n[Pre-Hook]\\nJust another stage\\nPageant the pain away\\nThis time I'm gonna take the crown\\nWithout falling down, down\\n\\n[Hook]\\nPretty hurts\\nWe shine the light on whatever's worse\\nPerfection is the disease of a nation\\nPretty hurts, pretty hurts\\nWe shine the light on whatever's worse\\nTryna fix something\\nBut you can't fix what you can't see\\nIt's my soul that needs the surgery\\n\\n[Verse 2]\\nBlonder hair, flat chest\\nTV says bigger is better\\nSouth beach, sugar free\\nVogue says thinner is better\\n\\n[Pre-Hook + Hook]\\n\\n[Bridge]\\nAin’t got no doctor or pill that can take the pain away\\nThe pain's inside\\nAnd nobody frees you from your body\\nIt's the soul, its the that needs surgery\\nIt's the soul that needs surgery\\nPlastic smiles and denial can only take you so far\\nThen you break when the fake facade leaves you in the dark\\nYou left a shattered mirror\\nAnd the shards of a beautiful girl\\n\\n[Hook]\\n\\n[Outro]\\nWhen you're alone all by yourself\\nAnd you're lying in your bed\\nReflection stares right into you\\nAre you happy with yourself?\\nIt's just a way to masquerade\\nThe illusion has been shed\\nAre you happy with yourself?\\nAre you happy with yourself?\\nYes\\n");
}
return v;
}
}
The error being:
String s = b.getInt("position");
As a new android developer, I'm not sure why? Please help.

The error is indicated by #JonasCz
you need to convert from int to String, because you can´t store an int into a String variable!
String s = String.valueOf(b.getInt("position"));

Figured this out. Changed the intent to Activity and the activity has this code:
public class SongLyrics extends Activity {
Context context;
String[] rank;
int position;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/** Setting the layout for this activity */
setContentView(R.layout.learnlyrics);
String title = getIntent().getExtras().getString("rank");
Intent i = getIntent();
position = i.getExtras().getInt("position");
rank = i.getStringArrayExtra("rank");
TextView titleTextView = (TextView) findViewById(R.id.learnsong);
// titleTextView.setText(title);
titleTextView.setText(rank[position]);
}
}

Related

Detecting when the keyboard is active in a webview

I have not yet found any way to solve this on stack.
I have a webview in my app. I want to be able to detect when the keyboard is active and when it is not active. It seems as if it cant detect these changes when they happon in a webview.
I want to perform actions on these different states. On iOS its really simple with observers that listens when the keyboard is active. Ref UIKeyboardWillShow/Hide.
Is there any functionality in android that does the same as these observers do in android?
Hopefully the question is well enough explained.
So I struggled with this a week or so and found a lot of material Here is my solution, I really hope that it works for you.
So in my case I have an Activity, and I call a fragment that contains the Webview so it was a lot trickier than I thought.
Basically the issue is that the fragment was missing this line:
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
So it didn't recognized the change of height inside the webview.
Anyways lets get to the code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
//mWebView.postUrl("https://www.google.com/");
final View activityRootView = view;
layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
// This variable was created only for Debug purposes and
// to see the height change when clicking on a field inside mWebView
int screenHeight = activityRootView.getRootView().getHeight();
Log.d("onGlobalLayout", "rect: " + r.toString());
Log.d("onGlobalLayout", "screenHeight: " + screenHeight);
//The difference on the heights from bottom to top and on the root height
int heightDiff = screenHeight - (r.bottom - r.top);
Log.d("onGlobalLayout", "heightDiff: " + heightDiff);
//I suggest to put 250 on resources and retrieve from there using getResources().getInteger() to have better order
float dpx = dpToPx(getActivity(), 250);
if (previousHeightDiff != heightDiff) {
if (heightDiff > dpx) {
isSoftKeyboardPresent = true;
} else {
isSoftKeyboardPresent = false;
}
previousHeightDiff = heightDiff;
}
}
};
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener);
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
return view;
}
private static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
Remember to put on your AndroidManifest.xml a setting on the activity set to: android:windowSoftInputMode="adjustResize|stateHidden"
The variables inside the fragment are:
public boolean isSoftKeyboardPresent = false;
private int previousHeightDiff = -1;// this is used to avoid multiple assignments
private ViewTreeObserver.OnGlobalLayoutListener layoutListener = null;
Finally
#Override
public void onPause() {
super.onPause();
final View activityRootView = getActivity().findViewById(R.id.page_content);
activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener);
}
And this should do the trick :) so what do you think?

Android: passing information from an array to a textview

I have set myself up an array with questions and answers as follows:
static String[][] question= new String[20][5];
{
question[0][0] = "what is my name?";
question[0][1] = "Mark";
question[0][2] = "Steven";
question[0][3] = "Alan";
question[0][4] = "Bob";
question[1][0] = "what is my age?";
question[1][1] = "30";
question[1][2] = "31";
question[1][3] = "32";
question[1][4] = "33";
}
first square brackets indicates the question number and the second number gives the answer number, all correct answers are in 4th answer.my intention is to build a general app of questions that randomize and to pass to the next screen. I have used this code to generate a random number for the question number. so for e.g. 1st attempt Q5 will come up, attempt 2 Q3 could come up, attempt 3 Q1 could come up etc.
This next block of code is used by the android:onClick="goToQuestions"
public void goToQuestions (View v)
{
Intent intent = new Intent (this, Questions.class);
startActivity(intent);
}
using the above code will successfully move from current activity to questions activity. If i use this code below:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_questions);
final TextView textView1 = (TextView) findViewById(R.id.textView1);
final Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
int randomArray = (int) (Math.random() *4);
textView1.setText(question[randomArray][0]);
}
});
}
it will allow me to generate a random number from the array of questions and print it to my text view when it is in the same activity. I have tried this code below to try to pass the information to the questions screen from the home screen:
public void goToQuestions (View v1)
{
final TextView textView1 = (TextView) findViewById(R.id.textView1);
int randomArray = (int) (Math.random() * 4);
textView1.setText(Questions.question[randomArray][0]);
Intent intent = new Intent (this, QuizActivity.class);
startActivity(intent);
}
I have assumed calling android:onClick eliminated the need for an onclick listener. Can anyone provide assistance for how I could finish this correctly. With that last piece of code the app just crashes as I hit the button.
Your data model is not ideal. Create a class that represents a question, and is Parcelable, so you can pass that to your next activity. Something like this
public class Question implements Parcelable {
private final String mQuestion;
private final List<String> mAnswers;
private final int mCorrectAnswer;
public Question(final String question, final List<String> answers, int correctAnswer) {
mQuestion = question;
mAnswers = answers;
mCorrectAnswer = correctAnswer;
}
// implement parcelable interface below
}
Then you would receive this on your next activity, deserialize it and show the data as you see fit.
Consider also using fragments instead of activities.
Found my issue, firstly thank you all for your assistance. Secondly I was able to do this task using the code I was using, I was just putting it into the wrong class files. I was able to move this code:
final TextView textView1 = (TextView) findViewById(R.id.textView1);
int randomArray = (int) (Math.random() * 4);
textView1.setText(Questions.question[randomArray][0]);
into my onCreate method and it worked fine.

Android - ArrayAdapter: set TextView to value from SQLiteDatabase

What I want to accomplish:
I want one TextView per row of a ListView to be dynamically set (its display text) to the value from a SQLite database.
What I tried:
Inside getView(), I assigned the said TextView via findViewById() to a global variable. Then I assigned the value position (from the parameter of getView()) to my global variable mListRowPosition. After this, I execute my AsyncTask sub-class via new AttemptGetCustomerInfo().execute().
My AsyncTask sub-class gets the SQLiteDatabase from my DatabaseHelper. With the mListRowPosition it receives the customer_id from the method getCustomerID() of the Service object inside the ArrayList<Service> dataset.
Together with the customer_id, it builds a SQL query to get the shortname of the customer. After querying, it gets the String shortname from the Cursor. I then setText(shortname) the global TextView from before (inside getView()).
The problems with that:
This 'kind of works' at some point, but it seems to be so slow that only the last (almost every time) has a value set as its text. Sometimes it also gets it wrong.
After debug-logging I saw that getView() gets called a lot faster than the AsyncTask is even finished (this makes sense, but it destroys my solution for my problem).
Also interesting: My debug log tells me that getView() gets called more often then there are data entries inside the ArrayList. If there are 5 entries, it will call getView() about 15 to 20 times. Why?
The code behind that:
public class ServiceAdapter extends ArrayAdapter<Service> {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Service service = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.listview_row, parent, false);
}
// Lookup view for data population
TextView quantity = (TextView) convertView
.findViewById(R.id.QUANTITY_CELL);
TextView description = (TextView) convertView
.findViewById(R.id.DESCRIPTION_CELL);
Button delete = (Button) convertView.findViewById(R.id.BUTTON_DELETE);
customerView = (TextView) convertView.findViewById(R.id.CUSTOMER_VIEW);
mListRowPosition = position;
Log.d("ServiceAdapter", "getView changed mListRowPositon to be "
+ String.valueOf(mListRowPosition));
new AttemptGetCustomerInfo().execute();
// Populate the data into the template view using the data object
quantity.setText(String.valueOf(service.getQuantity()));
description.setText(service.getDescription());
// Set up the listener for the delete button.
final int pos = position;
delete.setOnClickListener(new Button.OnClickListener() {
#Override
public void onClick(View v) {
showDialog("deleteButton", pos);
}
});
customerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showDialog("customerView", pos);
}
});
// Return the completed view to render on screen
return convertView;
}
class AttemptGetCustomerInfo extends AsyncTask<String, String, String> {
String shortname = null;
#Override
protected String doInBackground(String... params) {
DatabaseHelper db_helper = new DatabaseHelper(context);
SQLiteDatabase db = db_helper.getReadableDatabase();
Log.d("AttemptGetCustomerInfo",
"ListRowPos: " + String.valueOf(mListRowPosition));
Log.d("AttemptGetCustomerInfo", "description of ListRowPos: "
+ services.get(mListRowPosition).getDescription());
int customer_id = services.get(mListRowPosition).getCustomerID();
Log.d("AttemptGetCustomerInfo",
"customer id: " + String.valueOf(customer_id));
Cursor c = db.rawQuery(
"SELECT " + CustomerEntry.COLUMN_NAME_SHORTNAME + " FROM "
+ CustomerEntry.TABLE_NAME + " WHERE "
+ CustomerEntry.COLUMN_NAME_CUSTOMER_ID + "="
+ customer_id, null);
Log.d("AttemptGetCustomerInfo",
"available cursor size" + String.valueOf(c.getCount()));
if (c.getCount() == 0) {
Log.d("AttemptGetCustomerInfo", "There are no Cursor entries!");
return null;
}
c.moveToFirst();
shortname = c
.getString(c
.getColumnIndexOrThrow(CustomerEntry.COLUMN_NAME_SHORTNAME));
db.close();
return null;
}
#Override
protected void onPostExecute(String s) {
if (shortname != null) {
customerView.setText(shortname);
}
}
}
Additional info:
I didn't paste all of the code and a lot of code refering happens inside the above code to which no code is there also. I hope the function of my methods not shown are understandable via the method name.
So, lets begin.
If you want to display information from your database in your Listview I strongly recommend you using CursorAdapter instead of ArrayAdapter it will work far faster than it is probably now.
About the getView() calling, that happens because of the way Android paint listviews, the first time Android will call getView() several times in order to display properly things, if you change for example your ListView height from match_parent to wrap_content or viceversa you will notice that your getView() method will get called a different number of times.
Now about your code, you are not properly programming your getView() method. Inside the first part if (convertView == null) you should define your views using the ViewHolder pattern which will improve your performance.
Another problem I find here is that you are launching your AsyncTask everytime you your getView() method is called, that will produce a problem with your ListView scrolling as it will prevent of going smoothly (In a tablet for example you will run like 40 or 50 asynctask one after another, and that is a heavy workload).
If you want to keep your current code which I would strongly discourage you to do it, you will need a way of controlling if the current row have been executed your AsyncTask code in order to not repeat that work.
Hope it helps

Updating Fragments - FrameStatePagerAdapter and HTTP Calls

I have been searching for an answer to my problem, but I seem to get none, despite of how many tutorials I followed, how many questions I've gone through and how many things I've tried to do what I want. Basically, I stumbled upon some good tips, and still couldn't manage to do what wanted.
THE PROBLEM
I am creating an Android Application that will use Fragments (alongside with tabs). In these fragments, I have crucial information relating the application, such as text boxes, and buttons. However, I want to do something really simple, which is updating one of my fragments as I come back to it (imagine I swipe back to a fragment, and I update it with the relevant information). Where is the information stored? On a node.js server, to which I call every time I want information. So for that, I created the following structure.
THE STRUCTURE
First of all, I started off creating my Activity.
public class CentralActivity extends FragmentActivity {
CentralPagerAdapter mCentralActivity;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_central);
tabHandler();
}
public void tabHandler() {
mCentralActivity = new CentralPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.CentralPager);
mViewPager.setAdapter(mCentralActivity);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
getActionBar().setSelectedNavigationItem(position);
}
});
//Action Bar Stuff
}
}
With this said, I need my CentralPagerAdapter, which I created as follows.
public class CentralPagerAdapter extends FragmentStatePagerAdapter {
private int nSwipes = 3;
public CentralPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = new CentralFragment();
Bundle args = new Bundle();
args.putInt(CentralFragment.ARG_OBJECT, i + 1);
fragment.setArguments(args);
return fragment;
}
#Override
public int getCount() {
return nSwipes;
}
}
And now, my fragment, which is only a class that contains all of my views, and options and so on.
public class CentralFragment extends Fragment {
public static final String ARG_OBJECT = "object";
private View rootView;
private RESTFunction currentFunction;
//Has the info I want
private ArrayList<Integer> tickets = new ArrayList<Integer>();
#SuppressLint("HandlerLeak")
private Handler threadConnectionHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (currentFunction) {
case GET_CLIENT_TICKETS:
handleGetTickets(msg);
break;
case BUY_CLIENT_TICKETS:
break;
default:
break;
}
}
};
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
final Bundle args = getArguments();
handleFragments(inflater, container);
getTicketInfo(null);
return rootView;
}
private void handleFragments(LayoutInflater inflater, ViewGroup container) {
Bundle args = getArguments();
if (args.getInt(ARG_OBJECT) == 1) {
rootView = inflater.inflate(R.layout.fragment_show_tickets,
container, false);
showTicketsHandler();
} else if (args.getInt(ARG_OBJECT) == 2) {
rootView = inflater.inflate(R.layout.fragment_buy_tickets,
container, false);
buyTicketsHandler();
} else {
rootView = inflater.inflate(R.layout.fragment_history_tickets,
container, false);
}
}
public void showTicketsHandler() {
//Get stuff from the tickets array that the REST call will handle
//And set them to boxes or radio buttons
}
public void buyTicketsHandler() {
//Get stuff from the tickets array that the REST call will handle
//And set them to boxes or radio buttons
//As well as button click listeners
}
public void getTicketInfo(ProgressDialog progDialog) {
//Connect to the thread to get the information
//In this case, I have no parameters
ConnectionThread dataThread = new ConnectionThread("myLink", Method.GET, null, threadConnectionHandler, progDialog);
dataThread.start();
}
//Get stuff from the resulting JSON and store it in the tickets ArrayList
private void handleGetTickets(Message msg) {
JSONObject ticketListing = (JSONObject) msg.obj;
try {
tickets.add(ticketListing.getInt("t1"));
tickets.add(ticketListing.getInt("t2"));
tickets.add(ticketListing.getInt("t3"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
And then, I have my thread..
public class ConnectionThread extends Thread {
private ConnectionRunnable runConnection;
private Handler mHandler;
private ProgressDialog progDialog;
public ConnectionThread(String link, Method method, ArrayList<NameValuePair> payload, Handler handler, ProgressDialog progDialog) {
runConnection = new ConnectionRunnable(link, method.toString(), payload);
mHandler = handler;
this.progDialog = progDialog;
}
#Override
public void run() {
runConnection.run();
threadMsg();
if(progDialog != null)
progDialog.dismiss();
}
public JSONObject getJSON() {
return runConnection.getResultObject();
}
private void threadMsg() {
Message msgObj = mHandler.obtainMessage();
msgObj.obj = getJSON();
mHandler.sendMessage(msgObj);
}
}
And ConnectionRunnable is where I run my HttpURLConnection.
SO WHAT DO I NEED?
Basically, what I'm trying to do, is to get the ticket information from the ConnectionThread BEFORE I load all my view and update them. Plus, I want to be able to swipe back and forth, and update my information on the array as I swipe through the screens (if I go to the second screen, the tickets will update, and if I come back to the first, they will re-update). So basically, call the ConnectionThread everytime I swipe around. If that is possible that, is.
WHAT HAVE I TRIED?
I've tried several things already, and all of them didn't actually help..
The usage of ProgressDialogs to stop the UI Thread on the onCreateView method of the fragment (no use, because it returns the rootView before it handles everything);
Making the UI Thread sleep for 1 second (I don't know why, it blocks all of them);
Overriding the instantiateMethod() of the Adapter, although I think I didn't do it correctly;
Overriding the saveState() of the Adapter, in order to prevent its saved states, and to then get new ticket information;
Giving the fragments tags to update their rootViews on the Adapter, but to no avail;
Getting the information in the activity, and everytime I make a purchase (second fragment), restart the whole activity to get the tickets, which I believe is a really, really bad solution.
I've read several articles, and I still couldn't find my answers.. It's really frustrating. Because it's something so simple, however, the fact that I have to run the HTTP calls on a different thread delays the whole UI updating process.
I've also read the AsyncTask's method. However, I feel like both Threads and AsyncTasks end up in the same.
WHAT TO DO NOW?
Well, that's what I was hoping to find. Because it ends up being annoying as it is.
POSSIBLE REASONS
Is it because I'm separating all classes into spread files, therefore making my work difficult?
Thank you for your time, guys, hope we can find a solution or something.
THE EDIT
So basically, after 4 hours of reading documents and tutorials, I figured that what I needed was setOffscreenPageLimit(int). However, it can't be set to 0, so I will have to do with a setOnPageChangeListener. Now, to figure how to refresh the fragment, and I'll be as good as new.
Alright, it works perfectly! Basically, I did this:
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
((CentralFragment)((CentralPagerAdapter) mViewPager.getAdapter()).instantiateItem(mViewPager, position)).refresh();
getActionBar().setSelectedNavigationItem(position);
}
});
Where my .refresh is:
public void refresh() {
Bundle args = getArguments();
if (args.getInt(ARG_OBJECT) == 0) {
getTicketInfo(0);
} else if (args.getInt(ARG_OBJECT) == 1) {
getTicketInfo(1);
buyTicketsHandler();
} else {
//To Handle Later
}
}
It's as simple as refreshing the page before you go to it. Why didn't I remember this before..? So, here's the reference for those who ever need this!

Using a Spinner value in a calculation

Wondering if i can get some help with a problem i'm having? I have searched for the answer on here, and although i found a few relevant topics i'm still really struggling...
Below you can see that i'm using a Spinner asking the user to select either Large, Med or Small.
The selection is then issued to a TextView.
What i now want to do is assign a value to the 3 selections, Large = 6, Med = 4, Small =2.
Next there will be a EditText box for the user to add their own value.
Then i want to put the two values into a calculation (say * them in this example) putting the answer into a TextView.
Any help here would be great.
Many Thanks
Will
String[] items = { "Large", "Med", "Small" };
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.plugfan);
Factor = (TextView) findViewById(R.id.Factor);
Spinner spin = (Spinner) findViewById(R.id.spinner);
spin.setOnItemSelectedListener(this);
ArrayAdapter aa = new ArrayAdapter(
this,
android.R.layout.simple_spinner_item,
items);
aa.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(aa);
}
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
Factor.setText(items[position]);
}
public void onNothingSelected(AdapterView<?> parent) {
Factor.setText("");
}
A quick way to solve this (not the smartest one) is to have a paralell array:
int[] itemValues = { 6, 4, 2 };
In the method onItmeSelected you can setText using the itemValue, instead of items.
If you want a more OO-solution a new class that returns a list of Strings to use as a model for your spinner might be a beter solution (an enumeration might solve it too).

Categories