Day/Night Mode Not Working On Initial Startup - java

Very strange problem here. I'm going around in circles with it!
Day/Night mode seems to be working fine throughout my app...but for INVISIBLE drawables only, it is not working on initial load.
I have 2 xml drawable folders:
drawable and drawable-night with matching .png filenames
I have two values folders:
values with colors.xml, styles.xml, ic_launcher_background.xml and strings.xml - and also -
values-night with colors.xml and styles.xml
In the app I set the Mode using a toggle switch for Day/Night mode as per below. This seems to work fine.
dayNightMode.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
System.out.println("Not Checked");
InitApplication.getInstance().setIsNightModeEnabled(true, context);
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);
dayNightMode.setText("Night Mode");
} else {
System.out.println("Checked");
InitApplication.getInstance().setIsNightModeEnabled(false, context);
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
startActivity(intent);
dayNightMode.setText("Day Mode");
}
}
});
The InitApplication class being called by the above code is:
package com.dmurphy.remotescrumpoker;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class InitApplication extends Application {
public static final String NIGHT_MODE = "NIGHT_MODE";
private boolean isNightModeEnabled = false;
private static InitApplication singleton = null;
public static InitApplication getInstance() {
if(singleton == null)
{
singleton = new InitApplication();
}
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
Context appContext = this.getApplicationContext();
SharedPreferences sharedPreferences = appContext.getSharedPreferences("com.dmurphy.remotescrumpoker", Context.MODE_PRIVATE);
isNightModeEnabled = sharedPreferences.getBoolean(NIGHT_MODE, true);
Log.i("onCreate1_", String.valueOf(isNightModeEnabled));
}
public boolean isNightModeEnabled(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences("com.dmurphy.remotescrumpoker", Context.MODE_PRIVATE);
isNightModeEnabled = sharedPreferences.getBoolean(NIGHT_MODE, true);
Log.i("onCreate11_", String.valueOf(isNightModeEnabled));
return isNightModeEnabled;
}
public void setIsNightModeEnabled(boolean isNightModeEnabled, Context context) {
this.isNightModeEnabled = isNightModeEnabled;
Log.i("onCreate111_", String.valueOf(isNightModeEnabled));
SharedPreferences sharedPreferences = context.getSharedPreferences("com.dmurphy.remotescrumpoker", Context.MODE_PRIVATE);
sharedPreferences.edit().putBoolean(NIGHT_MODE, isNightModeEnabled).apply();
Log.i("onCreate1111_", String.valueOf(isNightModeEnabled));
}
}
I also have an Activity_Poker activity. Everything works fine, if I change the switch the app changes.
I also have a startup activity Activity_Splash and in the onCreate I check the mode:
if (InitApplication.getInstance().isNightModeEnabled(context)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
Log.i(TAG, "onCreate1_" + "Mode Night Yes");
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
Log.i(TAG, "onCreate1_" + "Mode Night No");
}
setContentView(R.layout.activity__splash);
The startup works fine. When I close the app and restart, the background color etc. is correct for both Modes. I have 3 drawables VISIBLE on the activity at all times. These also change fine between the two alternative modes.
However, I have 9 drawables which are INVISIBLE by default. These become VISIBLE onCreate, but they are always showing DAY_MODE on every load.
NOTE: The drawables are not in the wrong folders. The correct colors are in the correct folders. The color of the 9 .png files which are not working, matches the 3 VISIBLE drawables which work fine. Just the default INVISIBLE ones are not populating from the drawables-night folder onCreate.
If I restart the Activity using the inApp user menu, the activity is recreated correctly with the NIGHT_MODE or DAY_MODE drawables as applicable. But the NIGHT_MODE drawables (Fors ones which are INVISIBLE by default) are never used on startup.
EXPECTED OUTCOME: On Startup, ImageView's which are INVISIBLE are changed to VISIBLE and populated with drawables for DAY_MODE ordrawables-night for NIGHT_MODE.
ACTUAL OUTCOME: On Startup, ImageView's which are INVISIBLE are changed to VISIBLE and populated with drawables for DAY_MODE ordrawables for NIGHT_MODE.
Activity_Poker.java
public class Activity_Poker extends AppCompatActivity {
[snip]
Activity passedActivity = Activity_Poker.this;
[snip]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_poker);
drawerLayout = findViewById(R.id.drawer_layout);
[snip]
final String methodName = "onCreate";
mAuth = FirebaseAuth.getInstance();
String userId = mAuth.getUid();
[snip]
//Setup the UI for the selected game type
int cardType = sharedPreferences.getInt("cardType", 0);
Log.i(TAG, "Selected SharedPref Record: " + cardType);
callSetupUI.setupLocalActive(passedActivity, cardType);
[snip]
}
NOTE: cardType above shows correctly == 5 from the Logcat.
SetupUI.java
public void setupLocalActive(Activity passedActivity, int cardType) {
ImageView card4 = passedActivity.findViewById(R.id.pokerCard4);
ImageView card4img = passedActivity.findViewById(R.id.pokerCard4img);
ImageView card5 = passedActivity.findViewById(R.id.pokerCard5);
ImageView card5img = passedActivity.findViewById(R.id.pokerCard5img);
ImageView card6 = passedActivity.findViewById(R.id.pokerCard6);
ImageView card6img = passedActivity.findViewById(R.id.pokerCard6img);
ImageView card7 = passedActivity.findViewById(R.id.pokerCard7);
ImageView card7img = passedActivity.findViewById(R.id.pokerCard7img);
ImageView card8 = passedActivity.findViewById(R.id.pokerCard8);
ImageView card8img = passedActivity.findViewById(R.id.pokerCard8img);
ImageView card9 = passedActivity.findViewById(R.id.pokerCard9);
ImageView card9img = passedActivity.findViewById(R.id.pokerCard9img);
ImageView card11 = passedActivity.findViewById(R.id.pokerCard11);
ImageView card11img = passedActivity.findViewById(R.id.pokerCard11img);
TextView card4TextView = passedActivity.findViewById(R.id.textViewPokerCard4);
TextView card5TextView = passedActivity.findViewById(R.id.textViewPokerCard5);
TextView card6TextView = passedActivity.findViewById(R.id.textViewPokerCard6);
TextView card7TextView = passedActivity.findViewById(R.id.textViewPokerCard7);
TextView card8TextView = passedActivity.findViewById(R.id.textViewPokerCard8);
TextView card9TextView = passedActivity.findViewById(R.id.textViewPokerCard9);
TextView card10TextView = passedActivity.findViewById(R.id.textViewPokerCard10);
TextView card11TextView = passedActivity.findViewById(R.id.textViewPokerCard11);
TextView card12TextView = passedActivity.findViewById(R.id.textViewPokerCard12);
TextView card13TextView = passedActivity.findViewById(R.id.textViewPokerCard13);
TextView card14TextView = passedActivity.findViewById(R.id.textViewPokerCard14);
TextView card15TextView = passedActivity.findViewById(R.id.textViewPokerCard15);
Log.i(TAG, "Selected SharedPref Record UI CardType into Switch: " + cardType);
switch (cardType){
case 1:
[snip]
case 2:
[snip]
case 3:
[snip]
case 4:
[snip]
case 5:
Log.i(TAG, "Selected SharedPref Record Setting UI: " + cardType);
card10.setVisibility(card10.INVISIBLE);
card12.setVisibility(card12.INVISIBLE);
card13.setVisibility(card13.INVISIBLE);
card14.setVisibility(card14.INVISIBLE);
card15.setVisibility(card15.INVISIBLE);
card4TextView.setVisibility(card4TextView.INVISIBLE);
card5TextView.setVisibility(card5TextView.INVISIBLE);
card6TextView.setVisibility(card6TextView.INVISIBLE);
card7TextView.setVisibility(card7TextView.INVISIBLE);
card8TextView.setVisibility(card8TextView.INVISIBLE);
card9TextView.setVisibility(card9TextView.INVISIBLE);
card10TextView.setVisibility(card10TextView.INVISIBLE);
card11TextView.setVisibility(card10TextView.INVISIBLE);
card12TextView.setVisibility(card12TextView.INVISIBLE);
card13TextView.setVisibility(card13TextView.INVISIBLE);
card14TextView.setVisibility(card14TextView.INVISIBLE);
card15TextView.setVisibility(card15TextView.INVISIBLE);
card4img.setImageResource(R.drawable.chihuahua);
card5img.setImageResource(R.drawable.dachshund);
card6img.setImageResource(R.drawable.beagle);
card7img.setImageResource(R.drawable.spaniel);
card8img.setImageResource(R.drawable.boxer);
card9img.setImageResource(R.drawable.shepard);
card11img.setImageResource(R.drawable.dane);
card4img.setVisibility(card4img.VISIBLE);
card5img.setVisibility(card5img.VISIBLE);
card6img.setVisibility(card6img.VISIBLE);
card7img.setVisibility(card7img.VISIBLE);
card8img.setVisibility(card8img.VISIBLE);
card9img.setVisibility(card9img.VISIBLE);
card11img.setVisibility(card11img.VISIBLE);
break;
default:
[snip]
break;
}
}
activity_poker.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:layout_editor_absoluteX="16dp"
tools:layout_editor_absoluteY="260dp">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="32dp">
[snip]
<ImageView
android:id="#+id/pokerCard5"
android:layout_width="88dp"
android:layout_height="104dp"
android:layout_marginTop="16dp"
android:background="#color/colorPrimary"
android:contentDescription="#string/localCardSelectcontent"
android:onClick="card8clicked"
app:layout_constraintEnd_toStartOf="#+id/pokerCard6"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="#+id/pokerCard4"
app:layout_constraintTop_toBottomOf="#+id/pokerCard2" />
<ImageView
android:id="#+id/pokerCard5img"
android:layout_width="72dp"
android:layout_height="88dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:contentDescription="#string/localCardSelectcontent"
android:onClick="localcard5clicked"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="#+id/pokerCard5"
app:layout_constraintTop_toTopOf="#+id/pokerCard5"
app:srcCompat="#drawable/dachshund" />
<TextView
android:id="#+id/textViewPokerCard5"
android:layout_width="88dp"
android:layout_height="104dp"
android:onClick="localcard5clicked"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="#color/colorPrimaryDark"
android:textSize="44sp"
android:textStyle="normal|bold"
app:layout_constraintStart_toStartOf="#+id/pokerCard5"
app:layout_constraintTop_toTopOf="#+id/pokerCard5" />
<ImageView
android:id="#+id/pokerCard4"
android:layout_width="88dp"
android:layout_height="104dp"
android:background="#color/colorPrimary"
android:contentDescription="#string/localCardSelectcontent"
android:onClick="card5clicked"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="#+id/pokerCard5"
app:layout_constraintEnd_toStartOf="#+id/pokerCard5"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="#+id/pokerCard4img"
android:layout_width="72dp"
android:layout_height="88dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:contentDescription="#string/localCardSelectcontent"
android:onClick="localcard4clicked"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="#+id/pokerCard4"
app:layout_constraintTop_toTopOf="#+id/pokerCard4"
app:srcCompat="#drawable/chihuahua" />
<TextView
android:id="#+id/textViewPokerCard4"
android:layout_width="88dp"
android:layout_height="104dp"
android:onClick="localcard4clicked"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="#color/colorPrimaryDark"
android:textSize="44sp"
android:textStyle="normal|bold"
app:layout_constraintStart_toStartOf="#+id/pokerCard4"
app:layout_constraintTop_toTopOf="#+id/pokerCard4" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:onClick="onSwitchChange"
app:headerLayout= "#layout/nav_header_main"
app:menu="#xml/drawer_view" >
</com.google.android.material.navigation.NavigationView>

This is probably not the correct solution, but I implemented a workaround.
In Activity_Splash I added a bool to indicate that its the initial startup.
SharedPreferences sharedPreferences = Activity_Splash.this.getSharedPreferences("com.dmurphy.remotescrumpoker", Context.MODE_PRIVATE);
sharedPreferences.edit().putBoolean("initialStartup", true).apply();
In Activity_Poker I retrieved the bool and if NIGHT_MODE is enabled and 'initialStartup' is true, I restart the Activity_Poker to reset the UI.
boolean initialStartup = sharedPreferences.getBoolean("initialStartup", false);
if (InitApplication.getInstance().isNightModeEnabled(context) && initialStartup) {
callUserMenu.menuAction(TAG, methodName, context, 5, passedActivity); //This triggers my Intent to restart the activity
sharedPreferences.edit().remove("initialStartup").apply();
}
Still have no idea whats actually causing this.

Related

Why checkbox of android is so slow?

Today, I used an Android machine with poor performance. I found the checkbox loading is very slow.
For example:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
long t1 = System.currentTimeMillis();
setContentView(R.layout.activity_main);
System.out.println("main cost: " + (System.currentTimeMillis() - t1));
}
}
There is only one Checkbox in the page, this will cost 200ms. If there are 3 or 5 checkbox in activity_main.xml, will cost 1s. What happend?
I compared Switch to Checkbox. Obviously Switch is very very better than Checkbox. If i want to keep to use Checkbox, what should i do?
Why does it happen ?
This is happening because the Checkbox class is very complicated(too much code 😠).
What is the solution ?
You can create a custom layout.
You can use a library.
How to implement ?
1.Custom layout
First create a LinearLayout with horizontal orientation.
Add an ImageView and a TextView in the xml.
Code reference
<LinearLayout
android:id="#+id/checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="7dp">
<ImageView
android:id="#+id/checkImageView"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="#drawable/checked"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text for checkbox."
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"/>
</LinearLayout>
Now the code for it to work.
In your class add this
boolean isChecked = true
Now it will function like this
LinearLayout checkBox = findViewById( R.id.checkbox );
ImageView checkBoxImage = findViewById( R.id.checkImageView );
checkBox.setOnClickListener( v -> {
final Bitmap bmap = ((BitmapDrawable)checkBoxImage.getDrawable()).getBitmap();
Drawable myDrawable = getResources().getDrawable(R.drawable.checked);
final Bitmap myLogo = ((BitmapDrawable) myDrawable).getBitmap();
if (bmap.sameAs(myLogo)){
//it is checked
isChecked = false;
checkBoxImage.setImageResource( R.drawable.unchecked );
}else {
isChecked = true;
checkBoxImage.setImageResource( R.drawable.checked );
}
} );
2.Using a library
Use this library.
Sample usage
setChecked(boolean checked); //by default, it's wthout animation
setChecked(boolean checked, boolean animate); //pass true to animate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
final CustomCheckBox scb = (CustomCheckBox) findViewById(R.id.scb);
scb.setOnCheckedChangeListener(new CustomCheckBox.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CustomCheckBox checkBox, boolean isChecked) {
Log.d("CustomCheckBox", String.valueOf(isChecked));
}
});
}
Attributes
Attr
Type
Description
duration
integer
Animation Duration
stroke_width
dimension
The border width when unchecked
color_tick
color
Tick color (visible only when checked)
color_checked
color
Fill color when selected
color_unchecked
color
Fill color when unchecked
color_unchecked_stroke
color
Border color when unchecked
References
Github
Edit 1 (27/1/22)
Because of the comment received by Decent Dabbler , I now remember what it forgot. I actually forgot to mention that the file that takes too long to load is the xml file.This can be proved as we do not always use the class right? Just the view in the xml. If you open the xml file of the checkbox, you find it too big.

App crashes when I click the search button in my other fragments

My weather app works by searching cities on it's search panel and this works quite well. The only problem is that if i click the next tabs(hourly and daily section) on my bottom navigation view and
click the search button there, it shows the following exception:
java.lang.ClassCastException: com.viz.lightweatherforecast.SecondFragment cannot be cast to com.viz.lightweatherforecast.FirstFragment
at com.viz.lightweatherforecast.Activity.HomeActivity$2.onClick(HomeActivity.java:94)
at android.view.View.performClick(View.java:7044)
at android.view.View.performClickInternal(View.java:7017)
at android.view.View.access$3200(View.java:784)
at android.view.View$PerformClick.run(View.java:26596)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
This error clearly indicates that the error is from this line on the activity:
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
So I tried adding this:
SecondFragment secondFragment = (SecondFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
secondFragment.getWeatherData(textfield.getText().toString().trim());
So that it can support my secondfragment, but it still gave the error. I have as well searched this site for an answer, but haven't found any solution.
To explain the app further, I have an activity that hosts 3 fragments(Firstfragment, Secondfragment, and Thirdfragment. The 1st is labeled Today, 2nd is Hourly and 3rd is Daily for the weather.
I'm not planning on using the hourly and daily tabs for now until later versions of the app.
My other fragments are currently empty(no code written on them), I just want to stick to only the today tab for now.
But fixing this error is necessary, just in case of users click it.
My Aim is just to ensure that it doesn't give such an error if I click the search button on those other tabs, please help.
My Activity code:
public class HomeActivity extends AppCompatActivity {
// Last update time, click sound, search button, search panel.
TextView time_field;
MediaPlayer player;
ImageView Search;
EditText textfield;
// For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
ConstraintLayout constraintLayout;
public static int count=0;
int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// use home activity layout.
time_field = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
// find the id's of specific variables.
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
// host 3 fragments along with bottom navigation.
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
Search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// make click sound when search button is clicked.
player = MediaPlayer.create(HomeActivity.this, R.raw.click);
player.start();
getWeatherData(textfield.getText().toString().trim());
// make use of some fragment's data
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(#NonNull Call<Example> call, #NonNull Response<Example> response) {
try {
assert response.body() != null;
time_field.setVisibility(View.VISIBLE);
time_field.setText("Last Updated:" + " " + response.body().getDt());
} catch (Exception e) {
time_field.setVisibility(View.GONE);
time_field.setText("Last Updated: Unknown");
Log.e("TAG", "No City found");
Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(#NotNull Call<Example> call, #NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
}
Activity.xml code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
android:id="#+id/layout"
android:background="#drawable/dubai"
tools:context=".Activity.HomeActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_menu" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="409dp"
android:layout_height="599dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:navGraph="#navigation/my_nav"
/>
<EditText
android:id="#+id/textfield"
android:layout_width="250dp"
android:layout_height="35dp"
android:autofillHints="#string/change_city"
android:background="#color/colorPrimary"
android:hint="#string/search_city"
android:inputType="text"
android:labelFor="#id/imageView4"
android:padding="8dp"
android:textColor="#color/colorAccent"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="#+id/imageView4"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="#+id/imageView4"
android:layout_width="50dp"
android:layout_height="35dp"
android:layout_marginEnd="1dp"
android:contentDescription="#string/searchbtn"
android:src="#drawable/look"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/time_field"
android:visibility="gone"
android:textColor="#FFFFFF"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textfield" />
</androidx.constraintlayout.widget.ConstraintLayout>
To get a correct reference to the displayed fragment from NavHostFragment you have to check the Fragment Class Type first before you try to downcast it.
Based on your question:
App crashes when I click the search button in my other fragments
You cannot retrieve always the FirstFragment or SecondFragment instance as the visible Fragment when switching between other fragments.
So simply change your code to be like below:
Fragment currentFragment = (Fragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
if(currentFragment instanceof FirstFragment) {
FirstFragment firstFragment = (FirstFragment)currentFragment;
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof SecondFragment) {
SecondFragment secondFragment = (SecondFragment)currentFragment;
secondFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof ThirdFragment) {
ThirdFragment thirdFragment = (ThirdFragment)currentFragment;
thirdFragment.getWeatherData(textfield.getText().toString().trim());
}

Changing an image on a button click

iam new to android development and here iam trying to change images on a button click ,iam using the animate() method to fade one of the images and achieve the result .The first button click is fading the images but the second time i click on this button ,it doesnt give any result (images doesnt fade ) .
give me any possible solutions.thankyou
.java file
package e.nani.bestimage;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
public void change(View view) {
int flag=0;
ImageView img1 = (ImageView) findViewById(R.id.single);
ImageView img2 = (ImageView) findViewById(R.id.withands);
switch(flag){
case 0:img1.animate().alpha(0f).setDuration(2000);
img2.animate().alpha(1f).setDuration(2000);
flag=1;
break;
case 1: img1.animate().alpha(1f).setDuration(2000);
img2.animate().alpha(0f).setDuration(2000);
flag=0;
break;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView img1=(ImageView) findViewById(R.id.single);
ImageView img2=(ImageView) findViewById(R.id.withands);
img1.animate().alpha(1f).setDuration(2000);
img2.animate().alpha(0f).setDuration(2);
}
}
xml file
<?xml version="1.0" encoding="utf-8"?>
<android.widget.RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_purple"
tools:context=".MainActivity">
<ImageButton
android:id="#+id/single"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
app:srcCompat="#drawable/imgthree" />
<ImageView
android:id="#+id/withands"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:clickable="true"
app:srcCompat="#drawable/imgsix" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="98dp"
android:alpha="0.7"
android:background="#android:color/background_dark"
android:onClick="change"
android:text="find out the person"
android:textColor="#android:color/holo_blue_bright" />
</android.widget.RelativeLayout>
Anytime the change() method is called it's setting the flag equals to 0. Try this :
public class MainActivity extends AppCompatActivity {
int flag;
public void change(View view) {
ImageView img1 = (ImageView) findViewById(R.id.single);
ImageView img2 = (ImageView) findViewById(R.id.withands);
switch(flag){
case 0:
img1.animate().alpha(0f).setDuration(2000);
img2.animate().alpha(1f).setDuration(2000);
flag=1;
break;
case 1:
img1.animate().alpha(1f).setDuration(2000);
img2.animate().alpha(0f).setDuration(2000);
flag=0;
break;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
flag = 0;
ImageView img1=(ImageView) findViewById(R.id.single);
ImageView img2=(ImageView) findViewById(R.id.withands);
img1.animate().alpha(1f).setDuration(2000);
img2.animate().alpha(0f).setDuration(2);
}
}

Change background color of buttons from another activity onCheckedChange through shared preference(?)

I have 4 buttons in MainActivity that lead to different activities and by default they are set to have image background.
I click a button in main activity and it gets me to Options activity in where I have a switch.
'
//creates instance of the button and redirects to appropriate activity/class on button click
//options
Button options = findViewById(R.id.options);
options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intentOptions = new Intent(MainActivity.this, Options.class);
startActivity(intentOptions);
}
});
'
When that switch is checked I want for Options background(for user feedback) to change to a color and so 4 buttons in MainActivity (I don't want to start MainActivity).
However, I obviously get a null object reference error because I try to change smth in another activity.
I read a bunch of similar topics here and I understand that I should use Shared Preference to store smth(what?) that will allow me to change background of the buttons in another activity and then pass it (how?) to Options and pass it back(?) from Options on Switch check(???).
I am a newbie in java and android and I can't grasp how to solve my problem.
Code in Options class:
`
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.options);
//on toggle switch changes options background and activities buttons background in main layout to plain color
final Switch optionPlainColored = findViewById(R.id.switch1);
optionPlainColored.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ImageView background = findViewById(R.id.background);
Button attractionsAndArchitecture = findViewById(R.id.attractions_and_architecture);
Button barsAndRestaurants = findViewById(R.id.bars_and_restaurants);
Button sportAndRecreations = findViewById(R.id.sports_and_recreation);
Button nightlifeAndCulture = findViewById(R.id.culture_and_nightlife);
//on switch toggle changes background of options activity and 4 buttons in main activity
if(optionPlainColored.isChecked()){
background.setImageResource(R.drawable.setoptionsbackgroundcolor2);
attractionsAndArchitecture.setBackgroundColor(getResources().getColor(R.color.attractionsPlainColor));
barsAndRestaurants.setBackgroundColor(getResources().getColor(R.color.barsPlainColor));
sportAndRecreations.setBackgroundColor(getResources().getColor(R.color.sportsPlainColor));
nightlifeAndCulture.setBackgroundColor(getResources().getColor(R.color.culturePlainColor));
}else{
//when unchecked reverses the change
background.setImageResource(R.drawable.optionsbackground);
attractionsAndArchitecture.setBackground(getResources().getDrawable(R.drawable.placestovisitbackground));
barsAndRestaurants.setBackground(getResources().getDrawable(R.drawable.barandrestuarantsbackground));
sportAndRecreations.setBackground(getResources().getDrawable(R.drawable.sportandrecreationbackground));
nightlifeAndCulture.setBackground(getResources().getDrawable(R.drawable.nightlifeandculturebackground));
}
}
});
//displays toast message about the switch
Toast.makeText(getApplicationContext(), "Toggling the switch will change background color of the Options and Homescreen to plain colored one",
Toast.LENGTH_LONG).show();
}
`
Null object reference on lines where I am changing backgrounds.
XML on MainActivity:
'<?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"
android:background="#drawable/backgroundinfoadditional"
tools:context=".MainActivity">
<Button
android:id="#+id/attractions_and_architecture"
style="#style/buttonToActivity"
android:layout_width="205dp"
android:layout_height="285dp"
android:layout_marginBottom="8dp"
android:background="#drawable/placestovisitbackground"
android:text="#string/attractions_and_architecture"
app:layout_constraintBottom_toTopOf="#+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/bars_and_restaurants"
style="#style/buttonToActivity"
android:layout_width="208dp"
android:layout_height="280dp"
android:layout_marginBottom="8dp"
android:background="#drawable/barandrestuarantsbackground"
android:text="#string/bars_and_restaurants"
app:layout_constraintBottom_toTopOf="#+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/sports_and_recreation"
style="#style/buttonToActivity"
android:layout_width="208dp"
android:layout_height="284dp"
android:background="#drawable/sportandrecreationbackground"
android:text="#string/sports_and_recreation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="#+id/culture_and_nightlife"
style="#style/buttonToActivity"
android:layout_width="204dp"
android:layout_height="282dp"
android:background="#drawable/nightlifeandculturebackground"
android:text="#string/culture_and_nightlife"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title" />
<Button
android:id="#+id/options"
style="#style/options"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.024"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<Button
android:id="#+id/info"
style="#style/info"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.952"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/title"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:id="#+id/title"
style="#style/title"
android:layout_width="match_parent"
android:layout_height="39dp"
android:text="#string/moscow_concise_guide"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
'
use handler to pass message to mainactivity. like
if (MainActivity.xhandler != null) {
Message msg = new Message();
msg.what = message;
msg.obj = data1;
MainActivity.xhandler.sendMessage(msg);
}
In MainActivity define handler.
Handler xhandler=new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
return false;
}
});
Got an answer that worked from other source, posting it here (THIS DOES NOT USE SHARED PREFERENCES):
"I think that an alternative to using a separate Activity for the options, is using a DialogFragment. This would allow to show a floating window in the top of your MainActivity layout, and loading the options layout there, including the Switch.
Following this idea, instead of a new Activity, you’d need to create a DialogFragment for the options.
Then, let’s say you have a button in your Activity and you want to change the color. You can refer to the button like this
getActivity().findViewById(R.id.button)
and that’s it :slight_smile:
This way you can access any view in your Activity, change the background color, assign a different image, or whatever you want, without having to deal with preferences or access a different Activity."
OptionsDialogFragment class:
'
import android.app.DialogFragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
public class OptionsDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Here we inflate the layout to use with the options dialog
View dialogView = inflater.inflate(R.layout.options, container, false);
final Switch optionPlainColored = dialogView.findViewById(R.id.switch1);
optionPlainColored.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(optionPlainColored.isChecked()){
// we use getActivity() to refer to the views in the Activity layout.
getActivity().findViewById(R.id.attractions_and_architecture).setBackgroundColor(getResources().getColor(R.color.attractionsPlainColor));
getActivity().findViewById(R.id.bars_and_restaurants).setBackgroundColor(getResources().getColor(R.color.barsPlainColor));
getActivity().findViewById(R.id.sports_and_recreation).setBackgroundColor(getResources().getColor(R.color.sportsPlainColor));
getActivity().findViewById(R.id.culture_and_nightlife).setBackgroundColor(getResources().getColor(R.color.culturePlainColor));
} else {
getActivity().findViewById(R.id.attractions_and_architecture).setBackground(getResources().getDrawable(R.drawable.backgroundattractionsandarchitecture));
getActivity().findViewById(R.id.bars_and_restaurants).setBackground(getResources().getDrawable(R.drawable.backgroundbarsandrestaurants));
getActivity().findViewById(R.id.sports_and_recreation).setBackground(getResources().getDrawable(R.drawable.backgroundsportsandrecreation));
getActivity().findViewById(R.id.culture_and_nightlife).setBackground(getResources().getDrawable(R.drawable.backgroundnightlifeandculture));
}
}
});
return dialogView;
}
}'
In MainActivity:
' Button options = findViewById(R.id.options);
options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
OptionsDialogFragment dialogFrag = new OptionsDialogFragment();
FragmentManager fm = getFragmentManager();
dialogFrag.show(fm, "Options");
}
});'

TextView and scale

I use this code
TextView.animate().setDuration(0).scaleX(scale).scaleY(scale).start();
When scale value increase to some point, it make TextView disappear. I dont know why, and how to prevent it?
[Edit] Attach my test code
[test_text_scale.xml] It is Layout xml file for TestTextScale.java
<?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"
android:clipChildren="false"
android:orientation="vertical">
<TextView
android:id="#+id/tv_test_scale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Test" />
<Button
android:id="#+id/bt_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toEndOf="#+id/bt_down"
android:layout_toRightOf="#+id/bt_down"
android:text="Up" />
<Button
android:id="#+id/bt_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="Down" />
</RelativeLayout>
[TestTextScale.java]
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class TestTextScale extends AppCompatActivity {
// View
private TextView mTvTestZoom;
private Button mBtUp, mBtDown;
// Model
private int mCurrentScale = 1;
// OnClick listener
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_up : {
upScale();
setText();
} break;
case R.id.bt_down : {
downScale();
setText();
} break;
}
}
};
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_text_scale);
initView();
initEvent();
}
private void initView() {
mTvTestZoom = (TextView) findViewById(R.id.tv_test_scale);
mBtUp = (Button) findViewById(R.id.bt_up);
mBtDown = (Button) findViewById(R.id.bt_down);
}
private void initEvent() {
mBtDown.setOnClickListener(mOnClickListener);
mBtUp.setOnClickListener(mOnClickListener);
}
private void upScale() {
mCurrentScale += 1;
mTvTestZoom.animate().setDuration(0).scaleX(mCurrentScale).scaleY(mCurrentScale).start();
}
private void downScale() {
mCurrentScale -= 1;
mTvTestZoom.animate().setDuration(0).scaleX(mCurrentScale).scaleY(mCurrentScale).start();
}
private void setText() {
mTvTestZoom.setText(mCurrentScale + "");
}
}
This may happen because the textview exceeds the layout bounds of its parent. To overcome this, simple put android:clipChildren="false" in the xml description of the immediate parent of the textview. You may also need to do it for their parents too.
EDIT:
Upon testing the code myself, I found that the textview did disappear with following log message:
E/OpenGLRenderer: Font size too large to fit in cache. width, height = 635, 1028
This is due to a possible issue in the Android Hardware acceleration modules. One of the ways to avoid this is:
mTvTestZoom.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
This works well and the textView does not disappear after a certain size but, since it disables hardware acceleration for the specific textview, it may lose antialiasing.

Categories