Flutter test navigation by timer in initState - flutter-test

does anyone know how to test this type of navigation? Is there a way to test this kind of "automatic" navigation?
Timer? _timer;
#override
void initState() {
_timer = Timer(const Duration(milliseconds: 500), () {
Navigator.pushReplacementNamed(
context,
SplashPage.routeName,
);
});
super.initState();
}
#override
void dispose() {
_timer!.cancel();
super.dispose();
}

callNext(){
Future.delayed(const Duration(milliseconds: 2500), () {
setState(() {
Navigator.pushReplacementNamed(
context,
SplashPage.routeName,
);
});
});
}
in your init function call callNext();
init(){
callNext();
}

Related

Flutter/Dart How to adjust Modalbottomsheet animation speed?

I read this reference
https://api.flutter.dev/flutter/material/showModalBottomSheet.html
it says "transitionAnimationController parameters can be passed in to customize the appearance and behavior of modal bottom sheets.
The transitionAnimationController controls the bottom sheet's entrance and exit animations if provided."
but, I couldn't find any reference of transitionAnimationController,
so my question is, How can I adjust ModalBottomSheet Animation(entrance and exit speed that I want to adjust) with transitionAnimationController?
thank you.
If you are using a StatefulWidget add with TickerProviderStateMixin and create an AnimationController with BottomSheet.createAnimationController(this). You can then set the duration on the AnimationController. In this example I've set the duration to 3 seconds.
Make sure you dispose the AnimationController in void dispose ()
class MyModalBottomButton extends StatefulWidget {
#override
_MyModalBottomButtonState createState() => _MyModalBottomButtonState();
}
class _MyModalBottomButtonState extends State<MyModalBottomButton>
with TickerProviderStateMixin {
AnimationController controller;
#override
initState() {
super.initState();
controller =
BottomSheet.createAnimationController(this);
controller.duration = Duration(seconds: 3);
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return TextButton(
child: Text("Show bottom sheet"),
onPressed: () => showModalBottomSheet(
context: context,
transitionAnimationController: controller,
builder: (context) {
return Container(
child: Text("Your bottom sheet"),
);
},
),
);
}
}

CountDownTimer behaves weird/different the second time i open its Activity

I have been spending way too many hours on this one. And i just dont get it.
What i want: I have a main Activity (lets call it 'Activity Main') from which i am calling a second Activity ('Activity Timer') that has a CountDownTimer. Upon starting "Activity Timer" i want a Countdown to start running; it is only supposed to play a sound when it finishes. There is also a 'Pause-Button' which pauses/resumes the Countdown. 'Activity Timer' sends back results to 'Activity Main' via Intent when a button is pressed (either 'Success' or 'Fail' - well, it's a game). I am back at 'Activity Main' and all just worked perfectly fine.
That is until i start 'Activity Timer' a second time (for the secound round): The Countdown starts but cannot be paused. It just keeps ticking, even though i cancel() the Countdown and finish() the 'Activity Timer'.
Here's the code:
Activity Timer
public class GameActivity extends AppCompatActivity {
long countdown_time;
Button button_fail, button_success;
ImageButton imgbtn_pause;
boolean cd_running = false;
boolean countdown_auto = true;
TextView textView_countdown;
private static CountDownTimer;
Vibrator vibrator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_activity);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Preferences
prefs = getSharedPreferences("shared_preferences", Context.MODE_PRIVATE);
// Intent
Intent i = getIntent();
countdown_time = i.getLongExtra("countdown_time", 60000);
// Assigning
button_fail = (Button) findViewById(R.id.btn_fail);
button_success = (Button) findViewById(R.id.btn_success);
textView_countdown = (TextView) findViewById(R.id.tv_countdown);
imgbtn_pause = (ImageButton) findViewById(R.id.imgbtn_pause);
button_fail.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (cd_running) {
countdown.cancel();
}
cd_running = false;
countdown = null;
Intent returnIntent = new Intent();
if (risk) {
returnIntent.putExtra("result", "-3");
} else {
returnIntent.putExtra("result", "0");
}
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
});
button_success.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (cd_running) {
countdown.cancel();
}
cd_running = false;
countdown = null;
Intent returnIntent = new Intent();
setResult(Activity.RESULT_OK, returnIntent);
finish();
}
});
imgbtn_pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (cd_running) {
countdown.cancel();
cd_running = false;
imgbtn_pause.setBackgroundResource(R.drawable.play_2);
} else {
startCountDownTimer();
imgbtn_risk.setVisibility(View.INVISIBLE);
imgbtn_pause.setBackgroundResource(R.drawable.pause_2);
}
}
});
private void startCountDownTimer() {
cd_running = true;
imgbtn_pause.setBackgroundResource(R.drawable.pause_2);
countdown = new CountDownTimer(countdown_time, 1000) {
public void onTick(long millisUntilFinished) {
countdown_time = millisUntilFinished;
textView_countdown.setText("" + millisUntilFinished / 1000);
}
public void onFinish() {
countdown.cancel();
countdown = null;
cd_running = false;
if (!mute) {
vibrator = (Vibrator) GameActivity.this.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
countdown_sound.start();
}
textView_countdown.setVisibility(View.INVISIBLE);
textView_gameOver.setVisibility(View.VISIBLE);
imgbtn_pause.setVisibility(View.INVISIBLE);
}
}.start();
}
The call from 'Activity Main':
#Override
public void onClick(View view) {
Intent i = new Intent(GameMenu.this, GameActivity.class);
i.putExtra("countdown_time", countdown_time);
startActivityForResult(i, 1);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
String result_string = data.getStringExtra("result");
int result_int = Integer.parseInt(data.getStringExtra("result"));
}
if (resultCode == Activity.RESULT_CANCELED) {
// No result
}
}

How do I use a builder function? - flutter

I have asked a question named 'How to inject a Widget into a custom child Widget and use the child Widgets iteration index?' I already got an answer but there is a problem.
The answer said that I should:
"Instead of passing a Widget to your custom AppList you could pass a builder function that returns a Widget and takes the parameters as required, e.g. the index and whatever configuration is required. Something like the following:
Function definition:
typedef Widget MyListTileBuilder(String tileText);
then change the following:
final Widget child;
to
final MyListTileBuilder childBuilder;
of course you need to implement your builder method in Example Class:
Widget MyListTileBuilderImplementation (int index) {
return ListTile (
title: Text(installedApps[index]["app_name"]) //this is the text
),
}
when you build AppList inside example class you pass the method
AppList (
childBuilder: MyListTileBuilderImplementation
)
and finally inside AppList you call the builder, instead of adding child widget" :
itemBuilder: (context, index) {
return childBuilder(index); //This is where the ListTile will go.
},
So, I tried to edit my code. But for some reason it was not working. I think that I'm doing it wrong. Does anybody know how to solve this problem? (It would be very very helpful if you could edit my full code.)
Full Code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'dart:io';
import 'package:flutter_appavailability/flutter_appavailability.dart';
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(Example());
}
Future<void> getApp() async {
if (Platform.isAndroid) {
installedApps = await AppAvailability.getInstalledApps();
print(await AppAvailability.checkAvailability("com.android.chrome"));
print(await AppAvailability.isAppEnabled("com.android.chrome"));
}
else if (Platform.isIOS) {
installedApps = iOSApps;
print(await AppAvailability.checkAvailability("calshow://"));
}
}
List<Map<String, String>> installedApp;
List<Map<String, String>> installedApps;
List<Map<String, String>> iOSApps = [
{
"app_name": "Calendar",
"package_name": "calshow://"
},
{
"app_name": "Facebook",
"package_name": "fb://"
},
{
"app_name": "Whatsapp",
"package_name": "whatsapp://"
}
];
class Example extends StatefulWidget {
#override
ExampleState createState() => ExampleState();
}
class ExampleState extends State<Example> {
#override
Widget build(BuildContext context) {
return MaterialApp (
debugShowCheckedModeBanner: false,
home: Scaffold (
body: Container (
color: Colors.black,
child: AppList ()
)
),
);
}
}
class AppList extends StatefulWidget {
#override
AppListState createState() => AppListState();
AppList({Key key, this.child}) : super(key: key);
final Widget child;
}
class AppListState extends State<AppList> {
Widget child;
List<Map<String, String>> _installedApps;
#override
void initState() {
super.initState();
}
getApps() {
setState(() {
installedApps = _installedApps;
getApp();
});
}
#override
Widget build(BuildContext context) {
if (installedApps == null)
getApps();
return ListView.builder(
itemCount: installedApps == null ? 0 : installedApps.length,
itemBuilder: (context, index) {
return ListTile (
title: Text(installedApps[index]["app_name"])
);
},
);
}
}
This is your example with the changes:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'dart:io';
//import 'package:flutter_appavailability/flutter_appavailability.dart';
typedef Widget MyListTileBuilder(int index);
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(Example());
}
Future<void> getApp() async {
if (Platform.isAndroid) {
//installedApps = await AppAvailability.getInstalledApps();
//print(await AppAvailability.checkAvailability("com.android.chrome"));
//print(await AppAvailability.isAppEnabled("com.android.chrome"));
}
else if (Platform.isIOS) {
installedApps = iOSApps;
//print(await AppAvailability.checkAvailability("calshow://"));
}
}
List<Map<String, String>> installedApp;
List<Map<String, String>> installedApps=[
{"app_name":"app1"},
{"app_name":"app2"},
{"app_name":"app3"},
];
List<Map<String, String>> iOSApps = [
{
"app_name": "Calendar",
"package_name": "calshow://"
},
{
"app_name": "Facebook",
"package_name": "fb://"
},
{
"app_name": "Whatsapp",
"package_name": "whatsapp://"
}
];
class Example extends StatefulWidget {
#override
ExampleState createState() => ExampleState();
}
class ExampleState extends State<Example> {
Widget MyListTileBuilderImplementation (int index) {
return ListTile (
title: Text(installedApps[index]["app_name"] + " index:" + index.toString()) //this is the text
);
}
#override
Widget build(BuildContext context) {
return MaterialApp (
debugShowCheckedModeBanner: false,
home: Scaffold (
body: Container (
color: Colors.white,
child: AppList (childBuilder: this.MyListTileBuilderImplementation)
)
),
);
}
}
class AppList extends StatefulWidget {
#override
AppListState createState() => AppListState();
AppList({Key key, this.childBuilder}) : super(key: key);
final MyListTileBuilder childBuilder;
}
class AppListState extends State<AppList> {
List<Map<String, String>> _installedApps;
#override
void initState() {
super.initState();
}
getApps() {
setState(() {
installedApps = _installedApps;
getApp();
});
}
#override
Widget build(BuildContext context) {
if (installedApps == null)
getApps();
return ListView.builder(
itemCount: installedApps == null ? 0 : installedApps.length,
itemBuilder: (context, index) {
return widget.childBuilder(index);
},
);
}
}

Callbacks are not been called

I'm writing an app with Tango and getting a strange bug.
My program successfully connected to the tango service,and i have setup a callback with "mTango.connectListener(framePairs, new Tango.TangoUpdateCallback() {...});",but i can not get any tango datas because the callback have never been called.
here is my main code
private void bindTangoService() {
Log.d(TAG, "正在绑定Tango 服务");
if (mIsConnected) {
return;
}
mTango = new Tango(mContext, new Runnable() {
#Override
public void run() {
synchronized (TangoAR.this) {
try {
mConfig = setupTangoConfig(mTango, false, false);
mTango.connect(mConfig);
startupTango();
TangoSupport.initialize(mTango);
mIsConnected = true;
onRotationUpdated(Util.getDisplayRotation(mContext));
makeToast("tango 连接成功");
Log.d(TAG, "tango 连接成功");
} catch (TangoOutOfDateException e) {
makeToast("TangoOutOfDateException");
} catch (Throwable e) {
makeToast(e.getMessage());
}
}
}
});
}
private TangoConfig setupTangoConfig(Tango tango, boolean isLearningMode, boolean isLoadAdf) {
Log.d(TAG, "setupTangoConfig");
TangoConfig config = tango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
//在tango连接后使用相机必须使用true
config.putBoolean(TangoConfig.KEY_BOOLEAN_COLORCAMERA, false);
//motion
config.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING, true);
config.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY, true);
config.putBoolean(TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION, true);
//depth
config.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
config.putBoolean(TangoConfig.KEY_BOOLEAN_LOWLATENCYIMUINTEGRATION, true);
config.putInt(TangoConfig.KEY_INT_DEPTH_MODE, TangoConfig.TANGO_DEPTH_MODE_POINT_CLOUD);//使用点云,不使用老版本的TANGO_DEPTH_MODE_XYZ_IJ
//area learning
if (isLearningMode) {
//区域学习需要权限授权
if (checkAndRequestTangoPermissions(Tango.PERMISSIONTYPE_ADF_LOAD_SAVE)) {
Log.d(TAG, "PERMISSIONTYPE_ADF_LOAD_SAVE 开启");
config.putBoolean(TangoConfig.KEY_BOOLEAN_LEARNINGMODE, true);
}
}
if (isLoadAdf) {
//加载ADF
ArrayList<String> fullUuidList;
fullUuidList = tango.listAreaDescriptions();
if (fullUuidList.size() > 0) {
config.putString(TangoConfig.KEY_STRING_AREADESCRIPTION,
fullUuidList.get(fullUuidList.size() - 1));
}
}
return config;
}
private void startupTango() {
Log.d(TAG, "startupTango");
ArrayList<TangoCoordinateFramePair> framePairs = new ArrayList<>();
//设置参考系,0,0,0点为tango服务启动时设备的位置,测量目标为设备的位置
Log.d(TAG, "startup");
framePairs.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_DEVICE));
Log.d(TAG, "startup-listener");
mTango.connectListener(framePairs, new Tango.TangoUpdateCallback() {
#Override
public void onPoseAvailable(final TangoPoseData pose) {
//motion
Log.d(TAG, "onPoseAvailable");
//获取手机新的状态
mTangoTime = pose.timestamp;
TangoPoseData poseData = TangoSupport.getPoseAtTime(
mTangoTime,
TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR,
TangoSupport.ENGINE_OPENGL,
TangoSupport.ENGINE_OPENGL,
mDisplayRotation);
if (poseData.statusCode == TangoPoseData.POSE_VALID) {
mTangoPoseData = poseData;
}
}
#Override
public void onPointCloudAvailable(TangoPointCloudData pointCloud) {
//记录当扫描到到的深度信息
mPointCloudManager.updatePointCloud(pointCloud);
Log.d(TAG, "depth size:" + pointCloud.numPoints);
}
#Override
public void onXyzIjAvailable(TangoXyzIjData xyzIj) {
Log.d(TAG, "onXyzIjAvailable");
}
#Override
public void onFrameAvailable(int cameraId) {
Log.d(TAG, "onFrameAvailable");
}
#Override
public void onTangoEvent(TangoEvent event) {
Log.d(TAG, event.eventValue);
}
});
Log.d(TAG, "startup-listener-end");
}
mTango.connect(mConfig); execute successfully and without any exception.
I have been plagued by this problem for three days.I need a hero.Thanks everyone.
Notes:The rear camera is not be used for tango because i use it elsewhere.
I had the same problem. For me the solution was to request permissions:
startActivityForResult(
Tango.getRequestPermissionIntent(Tango.PERMISSIONTYPE_MOTION_TRACKING),
Tango.TANGO_INTENT_ACTIVITYCODE);

how to use RxBinding & Retrofit?

here is my code :
// Observable from RxView
RxView.clicks(mBtnLogin)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<Void>() {
#Override
public void call(Void aVoid) {
String userName = mEditUserName.getText().toString();
String passWord = mEditPassWord.getText().toString();
if (TextUtils.isEmpty(userName)) {
Toast.makeText(LoginActivity.this, R.string.input_user_name, Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(passWord)) {
Toast.makeText(LoginActivity.this, R.string.input_pass_word, Toast.LENGTH_SHORT).show();
return;
}
LoginAction action = Constants.retrofit().create(LoginAction.class);
// Observable from Retrofit
Observable<String> call = action.login(userName, MD5.encode(passWord));
call.subscribeOn(Schedulers.io())
.subscribe(new Observer<String>() {
#Override
public void onCompleted() {
System.out.println("completed");
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onNext(String s) {
System.out.println("next" + s);
}
});
}
});
Is there any way you could combine the Observable from RxView and the Observable from retrofit ?
i think the code is ugly and Do not meet the ReactiveX's specifications.
Yes, you would use the .flatMap() operator:
RxView.clicks(mButton)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.flatMap(new Func1<Void, Observable<Response>>() {
#Override
public Observable<Response> call(Void aVoid) {
return apiService.getResponse().subscribeOn(Schedulers.io());
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
would look a bit better with lambdas:
RxView.clicks(mButton)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribeOn(AndroidSchedulers.mainThread())
.flatMap(aVoid -> apiService.getResponse().subscribeOn(Schedulers.io()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe();

Resources