I am currently writing a flutter project in dart and build the android app from flutter. I currently have an image that covers the entire screen as the splash screen. Now I want to provide other images such that the app shows a random image each time the user opens the app.
I have searched "how to randomize splash screen for android" but it all needs to modify some java code (but I am writing a dart project). Is there another way like only modify .dart and/or .xml code?
I have added the second image to different places but none works. See below:
In launch_background.xml, the following only shows the splash_screen_1 image, splash_screen_2 is never shown.
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="fill_horizontal|fill_vertical"
android:src="#drawable/splash_screen_1" />
<bitmap
android:gravity="fill_horizontal|fill_vertical"
android:src="#drawable/splash_screen_2" />
</item>
</layer-list>
And the following only shows the splash_screen_2 image, splash_screen_1 is never shown.
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="fill_horizontal|fill_vertical"
android:src="#drawable/splash_screen_1" />
</item>
<item>
<bitmap
android:gravity="fill_horizontal|fill_vertical"
android:src="#drawable/splash_screen_2" />
</item>
</layer-list>
Is there a way to solve it in flutter? e.g. only modify .xml and/or .dart code and no need to modify java code? Thank you!
Try this:
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
Widget randomScreen(int max) {
var rnd = Random();
var num = rnd.nextInt(max);
print(num);
switch (num) {
case 1: return SecondSplashScreen();break;
case 2: return ThirdSplashScreen();break;
default: return FirstSplashScreen();break;
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: randomScreen(4),
);
}
}
class FirstSplashScreen extends StatefulWidget {
FirstSplashScreen({Key key}) : super(key: key);
_FirstSplashScreenState createState() => _FirstSplashScreenState();
}
class _FirstSplashScreenState extends State<FirstSplashScreen> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue
);
}
}
class SecondSplashScreen extends StatefulWidget {
SecondSplashScreen({Key key}) : super(key: key);
_SecondSplashScreenState createState() => _SecondSplashScreenState();
}
class _SecondSplashScreenState extends State<SecondSplashScreen> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red
);
}
}
class ThirdSplashScreen extends StatefulWidget {
ThirdSplashScreen({Key key}) : super(key: key);
_ThirdSplashScreenState createState() => _ThirdSplashScreenState();
}
class _ThirdSplashScreenState extends State<ThirdSplashScreen> {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green
);
}
}
Related
I followed stackoverflow answer and medium tutorial to make Splash Screen of Android version, but when I start the app, it shows Splash Screen a moment and stop the application.
My Splash Screen logo image directoy
launch_background.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/white" />
<item>
<bitmap
android:gravity="center"
android:src="#mipmap/splash_logo" />
</item>
</layer-list>
styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="#android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">#drawable/launch_background</item>
<item name="android:windowFullscreen">true</item>
</style>
</resources>
MainActivity.java
package com.example.privacyofanimal;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
public class MainActivity extends FlutterActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setStatusBarColor(0x00000000);
GeneratedPluginRegistrant.registerWith(this);
ViewTreeObserver vto = getFlutterView().getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
getFlutterView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
});
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(PrivacyOfAnimal());
}
class PrivacyOfAnimal extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: '동물의 사생활',
home: Test(),
debugShowCheckedModeBanner: false,
);
}
}
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}
}
My phone is Samsung Galaxy S8+ and I wanna fix this issue. What is the problem?
Error log
2019-01-23 16:44:03.443 18922-18922/com.handong.privacyofanimal
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.handong.privacyofanimal, PID: 18922
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.handong.privacyofanimal/com.handong.privacyofanimal.MainActivity}:
java.lang.ClassNotFoundException: Didn't find class
"com.handong.privacyofanimal.MainActivity" on path: DexPathList[[zip
file
"/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/base.apk"],nativeLibraryDirectories=[/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/lib/arm64,
/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/base.apk!/lib/arm64-v8a,
/system/lib64, /system/vendor/lib64]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2839)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.handong.privacyofanimal.MainActivity" on path: DexPathList[[zip
file
"/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/base.apk"],nativeLibraryDirectories=[/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/lib/arm64,
/data/app/com.handong.privacyofanimal-rCGlJOS-fSwTgzOMfceE0g==/base.apk!/lib/arm64-v8a,
/system/lib64, /system/vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at android.app.Instrumentation.newActivity(Instrumentation.java:1180)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2829)
I'm trying to implement a custom navigation drawer using react-navigation and react-native-elements. I also want all my screens to have a header (that has a hamburger from which I can control the drawer). The problem I'm facing is that the screen includes the header, while the drawer includes the screen, yet the header needs the drawer for its click event. So how do I pass the drawer object to my hamburger (inside the header component)?
The header in the file UniversalHeader.js is as follows
export default class UniversalHeader extends React.Component {
render() {
return (
<Header
leftComponent={{ icon: 'menu', color: '#ea0', onPress: () => this.props.navigation.navigate('DrawerToggle'), size: 50}}
centerComponent={{ text: this.props.label, style: { color: '#fff' } }}
/>
);
}
}
In my home screen, I have
import UniversalHeader from './UniversalHeader'
export default class HomeScreen extends React.Component {
render() {
return (
<View>
<UniversalHeader />
<Text> cards go here </Text>
</View>
);
}
}
Then in the compiling script collating the screens, I have
import HomeScreen from './home';
class customNav extends React.Component {
render() {
return (
<View>
<Avatar rounded xlarge source={require('./images/logo.png')} />
<DrawerNavigatorItems navigation={{state: [{routeName: 'Home', key: '0'}]}}
items={['Home', 'Discussions', 'Podcasts', 'Sermons', 'Events']}
onItemPress={route => this.props.navigation.navigate(route)}
renderIcon={(routeIcon) => (
<Image source={{uri: `./images/${routeIcon}.png`}} style={[styles.icon, {/*tintColor: tintColor*/}]} />
)}
getLabel={route => route.toString()}
/>
</View>
)
}
}
const MyApp = DrawerNavigator({
Home: {
screen: HomeScreen
}
}, {drawerBackgroundColor: '#000', contentComponent: customNav});
The onPress method in Header leftComponent has no idea of who navigator is but I don't know how to get it across either from the screen 'home.js' or from the 'UniversalHeader.js'.
The navigation property is automatically added to every component passed as a screen to any react-navigation component. So by proactively passing this.props.navigation of homescreen component to universalHeader i.e
<UniversalHeader navigation={this.props.navigation} />
You'll be giving it the navigator that's aware of all your registered classes/screen (in this case, passed into DrawerNavigator)
I am working on adding ripple effect when the preference is touched (selected). I have customized my preference by extending the ListPreference. I have tried to set the ripple effect programmatically by using RippleDrawable but I don't see the animation.
Here is my customized preference class
public class CustomListPreference extends ListPreference {
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomListPreference(Context context) {
super(context);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
setCustomStyle(view);
}
private void setCustomStyle(View view) {
TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setTypeface(InitActivity.TYPEFACE_REGULAR);
TextView summary = (TextView) view.findViewById(android.R.id.summary);
summary.setTypeface(InitActivity.TYPEFACE_REGULAR);
//Setting the drawable here, but it doesn't work.
RippleDrawable drawable = (RippleDrawable) getContext().getResources().getDrawable(R.drawable.my_ripple_background);
view.setBackGround(drawable);
}
}
My preferences layout
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- opens a subscreen of settings -->
<com.abc.app.CustomListPreference
android:defaultValue="1"
android:entries="#array/sampleEntries"
android:entryValues="#array/SampleEntryValues"
android:key="some_preference"
android:title="#string/some_preferences" />
<com.abc.app.CustomCheckboxPreference
android... />
</PreferenceScreen>
My ripple xml
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/light_black_overlay"> <!--#22000000-->
<item>
<shape
android:shape="rectangle">
<solid android:color="#android:color/background_light" />
</shape>
</item>
</ripple>
Am I setting the animation for the correct view? Any ideas are appreciated. Thanks.
This is a minimal complete example for adding a custom ripple effect to a class that extends ListPreference. I just made and tested this with API 21 (5.0).
SettingsActivity (Launch Activity)
public class SettingsActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
}
}
pref_general.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="true"
android:key="example_checkbox"
android:summary="a checkbox"
android:title="Checkbox test" />
<!-- replace with com.abc.app.CustomListPreference in your case-->
<com.timcastelijns.rippletest.CustomListPreference
android:defaultValue="1"
android:entries="#array/sampleEntries"
android:entryValues="#array/SampleEntryValues"
android:key="some_preference"
android:title="test" />
</PreferenceScreen>
arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="sampleEntries">
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string-array name="SampleEntryValues">
<item>4</item>
<item>5</item>
<item>6</item>
</string-array>
</resources>
CustomListPreference
public class CustomListPreference extends ListPreference {
private Context ctx;
public CustomListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
ctx = context;
}
public CustomListPreference(Context context) {
super(context);
ctx = context;
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
setCustomStyle(view);
}
private void setCustomStyle(View view) {
RippleDrawable drawable = (RippleDrawable) ctx.getDrawable(R.drawable.my_ripple_background);
view.setBackground(drawable);
}
}
my_ripple_background.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#android:color/holo_blue_light">
<item android:id="#android:id/mask">
<color android:color="#android:color/white" />
</item>
</ripple>
When pressed, it shows a light blue ripple effect, as specified in the xml:
I built this example based on your code, and code from the example SettingsActivity in the android SDK samples.
Edit:
After some time in chat and trying various things, we have come to a conclusion that the problem is caused by OP's phone (Samsung S5) or it's settings. When OP tried the code in the emulator, it all worked properly.
For reference - this is how it looked in OPs phone:
I want to update the layout of some items a in a ListView in an android app widget if a trigger is given. So I implemented below in getView() method in RemoteViewsService.RemoteViewsFactory.
public RemoteViews getViewAt(int position) {
...
int remoteViewId;
if (some condition) {
remoteViewId = R.layout.highlighted_item;
} else {
remoteViewId = R.layout.item;
}
RemoteViews rv = new RemoteViews(mContext.getPackageName(), remoteViewId);
This code works when the widget is loaded for the first time, but when updated using notifyAppWidgetViewDataChanged the layout persists and is not changed. How can I update xml layout used for a ListView item?
Change background
If my assumption is right and you are trying to highlight a list item by changing the background color or something similar I´d suggest to use a selector drawable instead of changing the layout programmatically:
drawable/list_item_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_activated="true"
android:drawable="#drawable/list_item_background_activated" />
<item
android:state_pressed="true"
android:drawable="#drawable/list_item_background_pressed" />
<item
android:drawable="#drawable/list_item_background" />
</selector>
drawable/list_item_background.xml
drawable/list_item_background_pressed.xml
drawable/list_item_background_activated.xml
Define such a drawable for each state in the selector and replace the 'color' with an appropriate color resource.
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="color" />
<stroke
android:width="1dp"
android:color="color" />
</shape>
Apply the list selector to the ListView in the widget´s layout:
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:listSelector="#drawable/list_item_selector" />
I use this for my own widget and it works perfectly.
For further information on state lists see this link.
Change entire layout
In order to change the entire layout try the following:
public class WidgetListProvider implements RemoteViewsFactory {
private boolean alternateLayout = 1;
#Override
public void onDataSetChanged() {
alternateLayout = alternateLayout == 1 ? 2 : 1;
}
#Override
public RemoteViews getViewAt(int position) {
final RemoteViews rv = new RemoteViews(_context.getPackageName(),
alternateLayout == 1 ? R.layout.list_row : R.layout.list_row2);
[...]
return rv;
}
#Override
public int getViewTypeCount() {
return 2;
}
[...]
}
Important: Note getViewTypeCount() - Because you use two different layouts, you have to return 2 here. If you return 1, a loading view will be displayed for the second layout.
So I am making an app with 3 buttons. Currently I have the following .xml file that makes them have rounded off edges and be the colour red. Now I want to to make them so if one is selected then that button turns green while the other two remain, or turn back to red. How could I go about doing this? Do I have to make another .xml file?
Here is my drawable .xml file for the buttons:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<!--red colour.-->
<solid android:color="#FF0000"/>
<corners
android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<stroke android:width="2px" android:color="#000000"/>
</shape>
Use a selector as follows:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- green state -->
<item
android:drawable="#drawable/button_selected"
android:state_selected="true"></item>
<!-- green state -->
<item
android:drawable="#drawable/button_pressed"
android:state_pressed="true"></item>
<!-- red state -->
<item
android:drawable="#drawable/button_disabled"></item>
</selector>
Then, you should call this selector like:
<Button
...
android:background="#drawable/my_selector" />
And create each drawable.xml (as your example for the red button) for every state: button_selected, button_pressed and button_disabled.
You can also remain the state by using onTouchListener like:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// change the color
return true;
case MotionEvent.ACTION_UP:
// intitial color
return true;
default:
return false;
}
}
});
However, it's better to use a Selector and a background, this use less resource.
UPDATE:
You can use a setBackgroundResource method to remain and change the background state of clicked button as follows:
// 1st clicklistener method
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button2.setBackgroundResource(R.drawable.selector_drawable);
}
}
// 2nd clicklistener method
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button1.setBackgroundResource(R.drawable.selector_drawable);
}
}
Not tested but it should work.