Main Menu Buttons change colour but dont understand how - java

I have a main menu with buttons (days of the week). If data is stored in the database in reference to these days of the week then they will turn 'green'. I understand the SQL query itself but don't understand how colourChange function identifies each button and 'knows' how to change it. Can someone maybe explain how this works?
MainMenu.java
private void colourChange() {
Cursor result = myDb.checkColour();
if (result.getCount() == 0) { // If the result equals to 0 then do nothing.
// Default colour remains
} else {
// if the result is not 0 then...
while (result.moveToNext()) { // Move through each result...
String day = result.getString(0); // and store the day (column 0) of the result in day
findViewById(getResources().getIdentifier(day + "button", "id", getPackageName())) // Find the view by ID using getResources.getIdentifier and passing the following parameter (day)
.setBackgroundColor(getResources().getColor(R.color.colorSuccess)); // The variable colourSuccess stored in the colours.xml file sets the background colour green.
}
}
}
Database.java
public Cursor checkColour() { // a SELECT statement is used to SELECT DayOfWeek FROM RoutineTable and GROUP BY DayOfWeek and store this as result.
SQLiteDatabase db = this.getWritableDatabase();
Cursor result = db.rawQuery("SELECT DayOfWeek FROM " + RoutineTable + " GROUP BY DayOfWeek", null);
return result;
}

Let's break the code down.
getResources().getIdentifier(day + "button", "id", getPackageName())
The Resources.getIdentifier() method allows you to access the various constants inside R.java dynamically, by name. day + "button" is the name of the resource and "id" is the type of the resource. So this method will return R.id.[day]button. If day holds "sunday", then you're going to get R.id.sundaybutton.
findViewById( [code from above] )
Now that getIdentifier() has returned a "real" id to you (like R.id.sundaybutton), findViewById() will search your layout for a View object with that android:id attribute. So if your layout includes a View with android:id="#+id/sundaybutton", findViewById(R.id.sundaybutton) will return it.
getResources().getColor(R.color.colorSuccess)
Resources.getColor() takes a color identifier (here R.id.colorSuccess) and returns the color value (perhaps it is green, maybe 0xFF00FF00).
setBackgroundColor( [color from above] )
This one is easy: it sets the background color of the specified View.
Altogether, you're going to iterate over the days of the week and
build an identifier from the day of the week
find a view using that identifier
get a color value from your resources
apply that color value to the found view's background
Hope this helps!

Good afternoon,
Without seeing all of the code for the resource file information for the application it will be hard to give you a definite answer. Looking at the code it looks like it matches a resource with the day of the week returned in the query plus the word "button" in the current application. Then it sets the background color by looking in the color resource folder for a resource called "colorSuccess", which changes it to the color green.

That colourChange() function firstly requesting to database return as cursor.
while (result.moveToNext()) is looping while all rows of result.
getResources().getIdentifier(day + "button", "id", getPackageName())
That find resources by specified layout id.Example "#+id/fridaybutton"
Accoriding android api documents. function paramters is here.
getIdentifier(String name, String defType, String defPackage)

Related

How can I get and set a string resource dynamically in a for-loop using a findViewById() method?

In my app, I want a counter from 0 to 8 to decide the number of players in a game.
Below there are 8 possible fields to write a name inside, which are all set to invisible. If the players-counter is set to 3 players, there should be the first 3 fields visible. Depending on the actual number of the counter, the visibility of the fields changes (1player = first field, 5 players = first 5 fields).
When the +1 (player) button is clicked, a certain method is activated. I tried to run a for-loop everytime the button is clicked. In this for-loop from 0 to "whatever amount" (max. 8 players) the actual fields should be found with "findById" and set to visible.
I tried it with a string resource (.xml) and I can get the text of the resource but with my thought process, I have to update the string resource to every number of the field (if 3 players: "field_" + "1", "field_" + "2", "field_" + "3").
How can I get and (most importantly) set/update a string resource for this specific purpose?
(Switch is too inefficient and I can't use a string with the findViewBy Id()-method by updating the String (not string resource) like mentioned before.
Please help, and accept the fact that I'm new to Android Studio for one week!)
You can use "getIdentifier" which takes a String parameter. So you can set the type as "id" in the second parameter of this method. This method returns the id of the view you want, but beware, it will throw a "FATAL EXCEPTION" if the id of the View doesn't exist. With this id, you can use findViewById to fetch the TextView and change its visibility. The "getIdentifier" method can be called from the "getResources()" method.
Below you can see what it would be like to make visible a TextView that has the id "textView1":
int id = getResources().getIdentifier("textView1", "id", getPackageName());
TextView textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
Below you can see how you would make 8 TextView with id 1 to 8 visible:
TextView textView;
for (int i = 1; i <= 8; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
So, just put the limit at i <= x , with x being the limit of players who will play:
TextView textView;
for (int i = 1; i <= totalPlayers; i++) {
int id = getResources().getIdentifier("textView" + i, "id", getPackageName());
textView = findViewById(id);
textView.setVisibility(View.VISIBLE);
}
Do you just want to make some EditTexts visible and others not? Personally I'd keep it simple, do the lookups once (in onCreate or wherever) and store the references in a list. Then when you need to display n fields, you can just iterate over the list and set the first n to VISIBLE and the rest to INVISIBLE.
I feel like it's fine to just list all the EditText IDs (R.id.field_1 etc) and generate your list of actual Views from that, but if that repetition bothers you, there's a few things you could do. Like:
set a tag attribute on each field in the XML, and use findViewWithTag to look them up, generating the lookup strings programmatically, like "field_" + i
do a similar thing with the resource ID, like in #Moises's answer
lookup their containing layout, use getChildCount and [getChildAt] to iterate over the views in that layout, and use isInstance to collect all the EditTexts in order3
create and add the EditTexts in code - you probably don't want to do this, but you could!
I'm not really sure what you mean about the string resource or what you're trying to do - I'd honestly just make a list of R.id.field_1 etc, iterate over that to do findViewById on each and store those in a new list, and you're done. Also my Java's a bit rusty so sorry no example code!

How to compare two datasets to check for missing rows which don't exist in the other dataset?

I have built a method which takes two datasets: dataset1 and retirementSimpleData.
It matches the two datasets based on a primary key/number, defined as cnum, in the code below.
I wanted to return the value of the difference between the getAssets value and the getSums value, and this is working, except for one little problem.
Some of the cnums that exist in dataset1 don't exist in retirementSimpleData. Similarly, some cnums which may exist in retirementSimpleData may not exist in
dataset1. This is resulting in no data being returned for that cnum.
I would like to implement two passes at the end which check in one direction to see if I missed anything. The second pass would check in the opposite direction.
However, not sure how I would go about implementing this.
public void getReportData(int index) {
String date1 = Util.dateTimeToShortString(reportDate);
String date2 = reportDao.getPreviousRetirementDate(date1);
List<SurveyCompareAssetsCheckData> dataset1 = reportDao.getSurveyCheckCompareAssetsData(date1);
List<RetSurveyAssets> retirementSimpleData = reportDao.findRetSurveyByDate(date1);
for (SurveyCompareAssetsCheckData surveyCompareAssetsCheckData : dataset1) {
for (RetSurveyAssets surveyCompareAssetsCheckData2 : retirementSimpleData) {
if (surveyCompareAssetsCheckData.getCnum() == surveyCompareAssetsCheckData2.getCnum()) {
surveyCompareAssetsCheckData.setRetirementsimple(surveyCompareAssetsCheckData2.getSums());
surveyCompareAssetsCheckData.setDifference(surveyCompareAssetsCheckData.getAssets() - surveyCompareAssetsCheckData2.getSums());
Caveat: dataset1 and retirementSimpledata both use existing SQL pulls which I am not allowed to touch, otherwise I would have simply defined new SQL for these methods in my "DAOImpl." Therefore, I have to work with the data I am getting, and programmatically check for this.
Below, is the report which is being generated with my code. As you can see, I am ending up with zeros, which is showing the difference (incorrectly) as zeros, because Cnum #45, in this example simply doesn't exist in the second dataset (retirementSimpleData)
What is the datatype of Cnum, if it is int then default value is Zero.
You have to add else-if condition to check for example:
else if (surveyCompareAssetsCheckData2.getCnum()== 0){
-------- logic here --------------------
}
else if (surveyCompareAssetsCheckData.getCnum() ==0){
----------logic here -----------
}

Is there a way to prevent an int value from deleting the first 0?

As the title says , for example I have the value 02 I want the first zero to stay there so I can control my pendingIntent.
my program basically has a list , every item has it's own options , the only way I can control alertmanager is by knowing the exact unique id so I can cancel the right notification , but I couldn't come up with a solution other than this:
int FirstListPosition = getArguments().getInt(EXTRA_FirstListPosition);
int InnerListPosition = getArguments().getInt(EXTRA_PASSEDPOSITION);
String Merge = Integer.toString(FirstListPosition) + Integer.toString(InnerListPosition);
int FinalValue = Integer.parseInt(Merge);
so if I click the first item in my main list , the FirstListPosition will be 0 and if I click the third item in my list inside of the main list the InnerListPosition will be 2
so the string merge will be = 02 , this way the unique id will never be the same and I can actually get the position of the two if the user wanted to cancel a specific pendingintent " notification "
hopefully you guys understood what I meant
Have a look at NumberFormat. This class is intended to be used to format number according to a specific pattern.
If you want to encode the position in two lists into a single int value (and the number of choices in the second list is, say, less than 1000 you might use:
int encodedListPositions;
int list1Position;
int list2Position;
int encodedListPosition = list1Position*1000 + list2Position;
...
list1Position = encodedListPosition / 1000;
list2Position = endocedListPosition - 1000*list1Position;

Obtaining current tab of ViewPager in Android [duplicate]

I know with the Gallery widget I was able to use getSelectedItemPosition(); to retrieve the current position, however it doesnt seem ViewPager has that.
I know I can setup a listener and retrieve the position when the page is switched. But I want the current view position.
You can use:
mViewPager.getCurrentItem()
Create a listener and set it on your viewpager:
/**
* Get the current view position from the ViewPager by
* extending SimpleOnPageChangeListener class and adding your method
*/
public class DetailOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
private int currentPage;
#Override
public void onPageSelected(int position) {
currentPage = position;
}
public final int getCurrentPage() {
return currentPage;
}
}
Update 2019
Now you can set addOnPageChangeListener on View Pager to Observe change in Page position.
Since you wanted to setup a listener and retrieve the position when the page is switched
mViewPager.addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
pagePosition.setText("" + position + "/" + galleryAdapter!!.count)
}
})
My solution would only work if you have a TabLayout linked to your ViewPager.
This is how they're linked:
tabLayout.setupWithViewPager(viewPager);
And then to get current position, you can make use of:
tabLayout.getSelectedTabPosition()
I'm telling you now its a hack, so there is no reason to downvote for that reason. Meaning, it either will be helpful to you specifically or not. Either way, the description below will provide some insight and be helpful to the community. Also, this solution is good for the older APIs that don't have ViewPager.getCurrentItem().
First, a little information. If you iterate thru all children of a ViewPager with ViewPager.getChildAt(x); and print out with toString() (or getLeft()) each child View (a page) and then do this everytime you change pages, you will notice that the children will not be in the logical order that they are displayed in when you start going back pages (paging back to the beginning). Apparently, it will remove the unneeded child from the array then append the newest child to the array. So, for example, lets say you are looking at page 2 then changed to page 3, your list of children will be in this order page 2, page 3, page 4 meaning that ViewPager.getChildAt(1); will return the current page. But, if you then change back to page 2 (from page 3) your list of children will be in this order page 2, page 3, page 1 which means that ViewPager.getChildAt(1); does not return the current page. I have not yet been able to find simple logic to weed out the current page using this information. Because the order of the pages in the array behind getChildAt is in an arbitrary order based off of how the user has been paging around.
That being said, I developed a hack work-around. I have no clue if this function will work in all in environments, but it works for my current project. I would suspect if doesn't for you, then its an issue of different API level. But I dont actually suspect any issues for other environments.
Now, onto the meat. What I noticed was that the result of ViewPager.getChildAt(x).getLeft() will have some type of horizontal pixel coordinate relative to the parent. So, I used this information to weed out which view is the current one.
private int getCurrentPageIndex(ViewPager vp){
int first,second,id1,id2,left;
id1 = first = second = 99999999;
View v;
for ( int i = 0, k = vp.getChildCount() ; i < k ; ++i ) {
left = vp.getChildAt(i).getLeft();
if ( left < second ) {
if ( left < first ) {
second = first;
id2 = id1;
first = left;
id1 = i;
} else {
second = left;
id2 = i;
}
}
}
return id2;
}
This function is probably a questionable hack because it relies on the value of getLeft() to figure it all out. But, I grab the left coordinate of each child. I then compare this to the other values and store the first and second pages, returning the second page (current page) out of the function. It seems to work beautifully.
Why (might you ask) didn't I just use onClickListenter or whatever solution? Well, I was darned determined that there was a straight forward way to do this without having to include listeners, other classes, inconclusive focus, and other bloat. Unfortunately, this solution is not exactly straight forward. But, it does do away with the bloat, other classes and listeners. If I can figure out a more straight forward way, I will be rewriting this function. Or maybe, this will provide insight for someone else to have an epiphany.

Android populate listview with cursor

My app uses a simple SQLite database. Everything works fine I can now present a Toast with a chosen row from the return query using:
{
//etc etc etc...
c.movetofirst();
DisplayTitle(c);
}
public void DisplayTitle(Cursor c)
{
Toast.makeText(main.this,
"id: " + c.getString(0) + "\n" +
"reg: " + c.getString(1) + "\n" +
"type: " + c.getString(2) + "\n",
Toast.LENGTH_LONG).show();
}
I want to prsent all the data in the cursor to the screen using a view but I am not sure how to go about this. Which view should I use? I just wnt a simple looking grid representation which allows me to scroll through each row in the cursor
Thanks in advance.
How can I show ALL rows in the Cursor?
There are several ways if you are working with a Cursor, for example see the "moveTo" related methods, here's an example:
Set<Item> items = new HashSet<Item>(c.getCount());
if (c.moveToFirst()) {
do {
Item i = new Item(select(c.getString(0), c.getString(1), c.getString(2));
set.add(i);
} while (c.moveToNext());
}
if (!c.isClosed()) {
c.close();
}
This assumes Item is a data class that has a constructor with three String parameters. Going with your code, id, reg, and type. Usually column 0 will be a numeric ID (not getString, but SQLite uses "manifest typing" so it will sort of dyna-type a String/Long from column 0 -- you may want to AUTOINCREMENT and use getLong there though).
One you have a collection of items, you can do anything you want with them to display them. If you want a scrolling/selectable list, then ListView is an excellent choice. And, you can back it with a CursorAdapter.
Here's an example of a ListView that is populated by a CursorAdapter from an open source project: http://code.google.com/p/and-bookworm/source/browse/trunk/src/com/totsp/bookworm/Main.java (see the inner BookCursorAdapter class, it should get you pointed in the right direction).

Categories