I am new to flutter and I'm trying to make tic tac toe game; i had some on ontap despite following the same concept in Flutter GestureDetector, onTap gets triggered automatically, how to?
My code to return the gridcells intially with red color and blank text
return Scaffold(
appBar: AppBar(title: Text('Tic Tac Toe')),
body: GridView.count(
crossAxisCount: 3,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
children: List<Widget>.generate(
9,
(int index){
return new GridCell(
index:index,
color: Colors.red,
text:Text(' '),
);
})));
Then the class of the gridcell is:
class GridCell extends StatefulWidget {
final Color color;
final Text text;
final int index;
GridCell({Key key, this.color,this.text,this.index}) :
super(key: key);
#override
GridCellState createState() {
return new GridCellState();
}
}
class GridCellState extends State<GridCell> {
Color cellColor=Colors.white;
Text cellText=new Text(' ');
String choice=' ';
#override
void initState() {
super.initState();
choice;
cellColor=widget.color;
cellText=widget.text;
}
//get text function to switch the x and o between the players
String _getText(){
if (choice=='X'){
choice='O';
}
else{
choice='X';
}
return choice;
}
_changeCell(index) {
setState(() {
switch (index) {
case 0:
cellColor = Colors.lightBlue;
cellText = new Text(choice);
print(_getText());
break;
case 1:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
print(_getText());
break;
case 2:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 3:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 4:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 5:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 6:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 7:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
case 8:
cellColor = Colors.lightBlue;
cellText = new Text(_getText());
print(_getText());
break;
}
});
}
#override
Widget build(BuildContext context) {
return new GestureDetector(
onTap:()=>_changeCell(widget.index),
child:Container(
height:20.0,
color:Theme.of(context).primaryColor,
),
);
}
}
The expected behaviour is 9 redgridcells appears and when i press one of the its text turns into X and its color turns into lightblue, the second press on another cell will have text O and color light blue the third's text is X and so on. The actual behaviour is 9 blue gridcells and when i press any of them nothing changes!
Thanks in advance:)
You are getting an error because choice is initialized to null and never really had a value before using it with Text(choice) or the conditional statement.
Add color: Colors.transparent, to the Container child of the GestureDetector
And your widget will looks:
#override
Widget build(BuildContext context) {
return new GestureDetector(
onTap:()=>_changeCell(widget.index),
child:Container(
height:20.0,
color:Theme.of(context).primaryColor,
),
);
}
Related
I created a CustomPainter which paints large canvas of volume 10000 elements.
A CustomPaint containing this painter is wrapped in a RepaintBoundary.
Problem: When I use Transform.scale of the parent widget, fps slowing down is observed.
For scaling used this library: gesture_zoom_box
Code snippet below:
import 'package:flutter/material.dart';
import 'package:gesture_zoom_box/gesture_zoom_box.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: MyWidget(),
);
}
}
Map _generateData() {
final Map classes = {
"0": {"color": "#BF1C1C", "marker": "X"},
"1": {"color": "#F06D06", "marker": "Y"},
"2": {"color": "#B742C9", "marker": "Z"}
};
final rows = [];
final Random random = Random();
final List keys = List.from(classes.keys);
final listC = new List<int>.generate(100, (i) => i + 1);
final listR = new List<int>.generate(100, (i) => i + 1);
for (final _ in listR) {
final List row = [];
for (final _ in listC) {
row.add({"type": "box", "cls": keys[random.nextInt(keys.length)]});
}
rows.add(row);
}
final Map data = {
"map": {
"rows": rows
},
"cls": classes
};
return data;
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext ctx) {
final Map data = _generateData();
return Scaffold(
appBar: AppBar(
title: Text("MyApp")
),
body: GestureZoomBox(
child: LayoutBuilder(
builder: (ctx, constraints) {
final int rowsNum = data["map"]["rows"].length;
final int colsNum = data["map"]["rows"][0].length;
final double boxSide = min(constraints.maxWidth/colsNum, constraints.maxHeight/rowsNum);
final double width = boxSide * colsNum;
final double height = boxSide * rowsNum;
return Center(
child: Container(
width: width,
height: height,
child: RepaintBoundary(
child: CustomPaint(
painter: PixelGridPainter(data: data)
),
),
),
);
}
)
)
);
}
}
class PixelGridPainter extends CustomPainter {
final Map data;
PixelGridPainter({this.data});
#override
void paint(Canvas canvas, Size size) {
final rows = data['map']['rows'];
final cls = data['cls'];
final double boxSide = min(size.width/rows[0].length, size.height/rows.length);
final Paint paint = Paint();
paint.style = PaintingStyle.fill;
var i = 0;
for (final row in rows) {
final rowOffset = boxSide * i;
var j = 0;
for (final elem in row) {
final columnOffset = j * boxSide;
final Map elemCls = cls[elem['cls']];
final Color c = Color(int.parse(elemCls["color"].substring(1, 7), radix: 16) + 0xFF000000);
paint.color = c;
final rect = Rect.fromLTRB(columnOffset, rowOffset, columnOffset + boxSide, rowOffset + boxSide);
canvas.drawRect(
rect,
paint,
);
j += 1;
}
i += 1;
}
}
#override
bool shouldRepaint(PixelGridPainter old) {
return true;
}
}
I tried PictureRecorder to draw only a picture and got the necessary 60fps, but I need quick interaction with this widget, which is impossible with such a hack without creating images cache.
Does anyone know what the problem is?
How would I move an image across an AnchorPane in JavaFX? The image should move itself over a period of time. So far I have: (view is the ImageView already in the AnchorPane)
position = 35.0;
for(int x = 0; x<11; x++){
TimeUnit.SECONDS.sleep(1);
myAnchorPane.getChildren().remove(view);
AnchorPane.setRightAnchor(view, position);
AnchorPane.setTopAnchor(view, 103.0);
myAnchorPane.getChildren().add(view);
position += 20;
}
within the initialize() method of my controller. However, this does not work since the stage appears with the image already moved.
Here is a class I create from an idea I got from tutoring a student.
You should use Javafx animation. This moves with button press, but if you
want to see the diver move right, just remove the code from inside the isRightPressed if-statement and place it outside the if-statement. Also, remove this part: * (Math.cos(Math.toRadians(rotation))).
import java.io.File;
import javafx.animation.AnimationTimer;
import javafx.event.EventHandler;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
/**
*
* #author blj0011
*/
public class Diver {
File diverFile;
ImageView ivDiver = new ImageView();
double rotation = 0.0;
boolean isUpPressed, isDownPressed, isLeftPressed, isRightPressed;
Diver()
{
diverFile = new File("src/img/diver.png");
if(diverFile.exists())
{
Image diverImage = new Image(diverFile.toURI().toString());
ivDiver.setImage(diverImage);
}
ivDiver.setFocusTraversable(true);
ivDiver.setOnKeyPressed(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
switch(event.getCode()) {
case UP: isUpPressed = true; break;
case DOWN: isDownPressed = true; break;
case LEFT: isLeftPressed = true; break;
case RIGHT: isRightPressed = true; break;
}
}
});
ivDiver.setOnKeyReleased(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent event) {
switch(event.getCode()) {
case UP: isUpPressed = false; break;
case DOWN: isDownPressed = false; break;
case LEFT: isLeftPressed = false; break;
case RIGHT: isRightPressed = false; break;
}
}
});
AnimationTimer timer = new AnimationTimer(){
#Override
public void handle(long now) {
if(isUpPressed){if(rotation == -360){rotation = 0;} ivDiver.setRotate(rotation+=5);}
if(isDownPressed){if(rotation == 360){rotation = 0;} ivDiver.setRotate(rotation-=5);}
if(isLeftPressed)
{
ivDiver.setX(ivDiver.getX() - 2.0 * (Math.cos(Math.toRadians(rotation))));
ivDiver.setY(ivDiver.getY() - 2.0 * (Math.sin(Math.toRadians(rotation))));
}
if(isRightPressed)
{
System.out.println("moving diver right!");
ivDiver.setX(ivDiver.getX() + 2.0 * (Math.cos(Math.toRadians(rotation))));
ivDiver.setY(ivDiver.getY() + 2.0 * (Math.sin(Math.toRadians(rotation))));
}
}
};
timer.start();
}
ImageView getDiver()
{
return ivDiver;
}
}
You code may look something like this.
AnimationTimer timer = new AnimationTimer(){
#Override
public void handle(long now) {
System.out.println("moving diver right!");
yourImageView.setX(yourImageView.getX() + 20.0 );
//yourImageView.setY(yourImageView.getY() + 20.0 );
}
};
timer.start();
i'm trying to implement a NSTableView in my project and fill it with specific data. This works quite fine. But now, i want to be able, to hide some columns, color specific cells, or color specific rows. I made something similar in java, but i really don't know to to do this in Xamarin:Mac.
Here is the code for my delegate:
public class Mp3FileTableDelegate : NSTableViewDelegate {
private const string CellIdentifier = "FileCell";
private Mp3FileDataSource DataSource;
public Mp3FileTableDelegate (Mp3FileDataSource datasource) {
this.DataSource = datasource;
}
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row) {
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = CellIdentifier;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = true;
view.EditingEnded += (sender, e) => {
SetNewValueInMp3File (DataSource.AudioFiles [(int)row], tableColumn, view.StringValue);
};
}
AudioFile audioFile = DataSource.AudioFiles [(int)row];
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Path":
view.StringValue = audioFile.getPathWithFilename ();
break;
}
if (audioFile.GetType () == typeof(Mp3File)) {
Mp3File mp3File = (Mp3File)audioFile;
switch (tableColumn.Title) {
case "Artist":
view.StringValue = mp3File.Artist;
break;
case "Title":
view.StringValue = mp3File.Title;
break;
case "Album":
view.StringValue = mp3File.Album;
break;
case "BPM":
view.StringValue = mp3File.BPM;
break;
case "Comment":
view.StringValue = mp3File.Comment;
break;
case "Year":
view.StringValue = mp3File.Year;
break;
case "Key":
view.StringValue = mp3File.InitialKey;
break;
case "Quality":
view.StringValue = mp3File.Album;
break;
case "Length":
view.StringValue = mp3File.Album;
break;
}
}
return view;
}
private void SetNewValueInMp3File (AudioFile file, NSTableColumn tableColumn, String value) {
if (file.GetType () == typeof(Mp3File)) {
Mp3File mp3File = (Mp3File)file;
switch (tableColumn.Title) {
case "Artist":
mp3File.Artist = value;
break;
case "Title":
mp3File.Title = value;
break;
case "Album":
mp3File.Album = value;
break;
case "BPM":
mp3File.BPM = value;
break;
case "Comment":
mp3File.Comment = value;
break;
case "Year":
mp3File.Year = value;
break;
case "Key":
mp3File.InitialKey = value;
break;
}
}
}
}
And here for my datasource:
public class Mp3FileDataSource : NSTableViewDataSource {
public List<AudioFile> AudioFiles = new List<AudioFile> ();
public Mp3FileDataSource () {
}
public override nint GetRowCount (NSTableView tableView) {
return AudioFiles.Count;
}
}
I would be very thankful, if anyone could help me a little.
Thanks
I have included the following line to show a simple timer in the top left corner of a scene, which works of course, but when I tick the Virtual Reality Supported check-box and put on an Oculus Rift, it disappears.
void OnGUI()
{
GUI.Label(new Rect(10, 10, 100, 20), Time.time.ToString());
}
What am I missing? What should I do additionally to resolve this?
OnGUI() does not work in VR. Instead use world space canvas UI.
I did the following for the Gear-VR.
Add a canvas (or other UI elements containing "Canvas" component) to your scene. Set render mode to World Space. This can be found on the render mode drop down list for the UI Canvas object:
I ended up going for an 800 x 600 canvas.
For the timer itself I used Time.deltaTime.
Here is my whole PlayerController script:
void Start ()
{
timeLeft = 5;
rb = GetComponent<Rigidbody>();
count = 0;
winText.text = "";
SetCountText ();
}
void Update() {
if (gameOver) {
if (Input.GetMouseButtonDown(0)) {
Application.LoadLevel(0);
}
} else {
timeLeft -= Time.deltaTime;
timerText.text = timeLeft.ToString("0.00");
if (timeLeft < 0) {
winner = false;
GameOver(winner);
}
}
}
void GameOver(bool winner) {
gameOver = true;
timerText.text = "-- --";
string tryAgainString = "Tap the touch pad to try again.";
if (!winner) { // case A
winText.text = "Time's up.\n" + tryAgainString;
}
if (winner) { // case B
winText.text = "Well played!\n" + tryAgainString;
}
}
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Mouse X");
float moveVertical = Input.GetAxis ("Mouse Y");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce (movement * speed);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ( "Pick Up")){
other.gameObject.SetActive (false);
count = count + 1;
SetCountText ();
if (!gameOver) {
timeLeft += 3;
}
}
}
void SetCountText ()
{
if (!gameOver) {
countText.text = "Count: " + count.ToString ();
}
if (count >= 12) {
winner = true;
GameOver(winner);
}
}
OnGUI does not work in VR. You have to use world space canvas UI.
My requirement is to take picture from the camera or pick a image from the gallery and show it in a image view.. After showing the image I'm sending as a mail whatever the image is selected. My issues is every time i take a portrait picture form the camera it rotates and show it in the image view. How to fix this issue.
thanks in advance.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.skicka_bild_activity);
share = new Sharedprefs(SkickaBild.this);
emailSendButton = (Button) findViewById(R.id.skicka_button);
emailSendButton.setOnClickListener(this);
emailSendButton.setEnabled(false);
Button camaraOnButtton = (Button) findViewById(R.id.fotografera_button);
camaraOnButtton.setOnClickListener(this);
Button galleryOpenButton = (Button) findViewById(R.id.valj_bild_button);
galleryOpenButton.setOnClickListener(this);
imageSetImageView = (ImageView) findViewById(R.id.imageView_skick);
maxWidth = share.getmaxwidth();
mContentResolver = getContentResolver();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.skicka_button:
if (isImageViewFilled) {
showEmailComposer();
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(
SkickaBild.this);
builder.setTitle("Alert !!");
builder.setMessage("Pick a image before you send the email")
.setCancelable(false)
.setPositiveButton("Ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
break;
case R.id.fotografera_button:
share.setisFromTabsClearImage(false);
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent takePictureIntent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
mCapturedImageURI);
startActivityForResult(takePictureIntent, 0);
break;
case R.id.valj_bild_button:
share.setisFromTabsClearImage(false);
Intent pickPhoto = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto, 1);
break;
}
}
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case 0:
if (resultCode == RESULT_OK) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(mCapturedImageURI,
projection, null, null, null);
int column_index_data = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String capturedImageFilePath = cursor
.getString(column_index_data);
Bitmap mImageBitmap = BitmapFactory
.decodeFile(capturedImageFilePath);
imageSetImageView.setImageBitmap(mImageBitmap);
isImageViewFilled = true;
if (isImageViewFilled) {
emailSendButton.setEnabled(true);
emailSendButton.setBackgroundDrawable(getResources()
.getDrawable(R.drawable.skicka_button_black));
}
File root = Environment.getExternalStorageDirectory();
if (root.canWrite()) {
System.out.println("PICTURE PATH " + capturedImageFilePath);
pic = new File(capturedImageFilePath);
String cPath = pic.getAbsolutePath();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(cPath, bmOptions);
float photoW = mImageBitmap.getWidth();
float photoH = mImageBitmap.getHeight();
// Get the dimensions of the View
float targetW = Float.parseFloat(maxWidth);
float targetH = (photoH / photoW) * targetW;
System.out.println("cam bitmap height"
+ mImageBitmap.getHeight());
System.out.println("cam bitmap weidth" + maxWidth);
System.out.println("cam bitmap Width 02 "
+ mImageBitmap.getWidth());
System.out.println("cam target Height " + targetH);
System.out.println("cam target width " + targetW);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = (int) scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(cPath, bmOptions);
mImageBitmap = Bitmap.createScaledBitmap(bitmap,
(int) targetW, (int) targetH, false);
FileOutputStream fout;
try {
fout = new FileOutputStream(pic);
mImageBitmap.compress(Bitmap.CompressFormat.JPEG, 100,
fout);
fout.flush();
fout.close();
bitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
}
break;
case 1:
if (resultCode == RESULT_OK) {
Uri selectedImage = imageReturnedIntent.getData();
InputStream in = null;
String[] filePathColumn = { MediaStore.Images.Media.DATA };
try {
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
System.out.println("PICTUREPATH" + picturePath);
cursor.close();
Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
int orientation = getOrientation(this, selectedImage);
System.out.println("ORIENTATION VALUE " + orientation);
imageSetImageView.setImageBitmap(imageBitmap);
isImageViewFilled = true;
if (isImageViewFilled) {
emailSendButton.setEnabled(true);
emailSendButton.setBackgroundDrawable(getResources()
.getDrawable(R.drawable.skicka_button_black));
}
// ////////////////////////// Image is set ///////////////
pic = new File(picturePath);
String cPath = pic.getAbsolutePath();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(cPath, bmOptions);
float photoW = imageBitmap.getWidth();
float photoH = imageBitmap.getHeight();
// Get the dimensions of the View
float targetW = Float.parseFloat(maxWidth);
float targetH = (photoH / photoW) * targetW;
System.out.println(" bitmap height"
+ imageBitmap.getHeight());
System.out.println(" bitmap weidth" + maxWidth);
System.out.println(" bitmap Width 02 "
+ imageBitmap.getWidth());
System.out.println(" target Height " + targetH);
System.out.println(" target width " + targetW);
float scaleFactor = Math.min(photoW / targetW, photoH
/ targetH);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = (int) scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(cPath, bmOptions);
imageBitmap = Bitmap.createScaledBitmap(bitmap,
(int) targetW, (int) targetH, false);
FileOutputStream fout;
fout = new FileOutputStream(pic);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fout);
fout.flush();
fout.close();
bitmap.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
break;
}
}
public static int getOrientation(Context context, Uri photoUri) {
String[] orientationColumn = { MediaStore.Images.Media.ORIENTATION };
Cursor cursor = context.getContentResolver().query(photoUri,
orientationColumn, null, null, null);
try {
if (cursor.moveToFirst()) {
return cursor.getInt(cursor
.getColumnIndex(orientationColumn[0]));
} else {
return -1;
}
} finally {
cursor.close();
}
}
private void showEmailComposer() {
Intent email = new Intent(Intent.ACTION_SEND);
email.putExtra(Intent.EXTRA_EMAIL, new String[] { share.getMailTo() });
email.putExtra(Intent.EXTRA_SUBJECT, share.getsubject());
email.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(pic));
// email.putExtra(Intent.EXTRA_STREAM, pic.getName());
email.putExtra(Intent.EXTRA_TEXT, share.getemailbody());
email.setType("message/rfc822");
startActivity(Intent.createChooser(email, "Choose an Email client :"));
isEmailSend = true;
}
#Override
protected void onResume() {
super.onResume();
System.out.println("ON RESUME INCOMING CHECK");
if (share.getisFromTabsClearImage()) {
imageSetImageView.setImageDrawable(getResources().getDrawable(
R.drawable.ingenbildvald));
emailSendButton.setBackgroundDrawable(getResources().getDrawable(
R.drawable.skicka_button));
emailSendButton.setEnabled(false);
share.setisFromTabsClearImage(false);
}
if (isEmailSend) {
imageSetImageView.setImageDrawable(getResources().getDrawable(
R.drawable.ingenbildvald));
emailSendButton.setBackgroundDrawable(getResources().getDrawable(
R.drawable.skicka_button));
emailSendButton.setEnabled(false);
isEmailSend = false;
}
}