I am trying to get the center of the screen when I initialize a class.
I have gotten that using CustomPainter like this:
class Pinter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
final Offset center = size.center(Offset.zero);
But I just can get the center when I call that class, I would like to get the center of the screen when a variable is initialized.
How i can get it?
You should use a MediaQuery object for that:
final size = MediaQuery.of(context).size;
final center = Offset(size.width/2, size.height/2);
Look at the documentation.
Related
I am trying to create a border with curved lines and rounded corners in Flutter. I was able to curve the lines using shapemaker.web.app, but I was not able to round the corners.
I have already tried it with a ClipPath + Clipper:
class NativeClipper extends CustomClipper<Path> {
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
#override
Path getClip(Size size) {
Path path0 = Path();
path0.moveTo(size.width*0.0833333,size.height*0.0714286);
path0.lineTo(size.width*0.9166667,size.height*0.0714286);
path0.quadraticBezierTo(size.width*0.9583333,size.height*0.5000143,size.width*0.9166667,size.height*0.9285714);
path0.cubicTo(size.width*0.7083333,size.height*0.9285714,size.width*0.2916667,size.height*0.9285714,size.width*0.0833333,size.height*0.9285714);
path0.quadraticBezierTo(size.width*0.0416833,size.height*0.5001143,size.width*0.0833333,size.height*0.0714286);
return path0;
}
}
Current Result:
Expected Result: (do not pay attention to the Colors)
I'm writing my first Qt 5 application... This uses a third-party map library (QGeoView).
I need to draw an object (something like a stylized airplane) over this map. Following the library coding guidelines, I derived from the base class QGVDrawItem my QGVAirplane.
The airplane class contains heading and position values: such values must be used to draw the airplane on the map (of course in the correct position and with correct heading). The library requires QGVDrawItem derivatives to override three base class methods:
QPainterPath projShape() const;
void projPaint(QPainter* painter);
void onProjection(QGVMap* geoMap)
The first method is used to achieve the area of the map that needs to be updated. The second is the method responsible to draw the object on the map. The third method is needed to reproject the point from the coordinate space on the map (it's not relevant for the solution of my problem).
My code looks like this:
void onProjection(QGVMap* geoMap)
{
QGVDrawItem::onProjection(geoMap);
mProjPoint = geoMap->getProjection()->geoToProj(mPoint);
}
QPainterPath projShape() const
{
QRectF _bounding = createGlyph().boundingRect();
double _size = fmax(_bounding.height(), _bounding.width());
QPainterPath _bounding_path;
_bounding_path.addRect(0,0,_size,_size);
_bounding_path.translate(mProjPoint.x(), mProjPoint.y());
return _bounding_path;
}
// This function creates the path containing the airplane glyph
// along with its label
QPainterPath createGlyph() const
{
QPainterPath _path;
QPolygon _glyph = QPolygon();
_glyph << QPoint(0,6) << QPoint(0,8) << QPoint(14,6) << QPoint(28,8) << QPoint(28,6) << QPoint(14,0);
_path.addPolygon(_glyph);
_path.setFillRule(Qt::FillRule::OddEvenFill);
_path.addText(OFF_X_TEXT, OFF_Y_TEXT, mFont , QString::number(mId));
QTransform _transform;
_transform.rotate(mHeading);
return _transform.map(_path);
}
// This function is the actual painting method
void drawGlyph(QPainter* painter)
{
painter->setRenderHints(QPainter::Antialiasing, true);
painter->setBrush(QBrush(mColor));
painter->setPen(QPen(QBrush(Qt::black), 1));
QPainterPath _path = createGlyph();
painter->translate(mProjPoint.x(), mProjPoint.y());
painter->drawPath(_path);
}
Of course:
mProjPoint is the position of the airplane,
mHeading is the heading (the direction where the airplane is pointing),
mId is a number identifying the airplane (will be displayed as a label under airplane glyph),
mColor is the color assigned to the airplane.
The problem here is the mix of rotation and translation. Transformation: since the object is rotated, projShape() methods return a bounding rectangle that's not fully overlapping the object drawn on the map...
I also suspect that the center of the object is not correctly pointed on mProjPoint. I tried many times trying to translate the bounding rectangle to center the object without luck.
Another minor issue is the fillup of the font... the label under the airplane glyph is not solid, but it is filled with the same color of the airplane.
How can I fix this?
Generically speaking, the general pattern for rotation is to scale about the origin first and then finish with your final translation.
The following is pseudocode, but it illustrates the need to shift your object's origin to (0, 0) prior to doing any rotation or scaling. After the rotate and scale are done, the object can be moved back from (0, 0) back to where it came from. From here, any post-translation step may be applied.
translate( -origin.x, -origin.y );
rotate( angle );
scale( scale.x, scale y);
translate( origin.x, origin.y );
translate( translation.x, translation.y )
I finally managed to achieve the result I meant....
QPainterPath projShape() const
{
QPainterPath _path;
QRectF _glyph_bounds = _path.boundingRect();
QPainterPath _textpath;
_textpath.addText(0, 0, mFont, QString::number(mId));
QRectF _text_bounds = _textpath.boundingRect();
_textpath.translate(_glyph_bounds.width()/2-_text_bounds.width()/2, _glyph_bounds.height()+_text_bounds.height());
_path.addPath(_textpath);
QTransform _transform;
_transform.translate(mProjPoint.x(),mProjPoint.y());
_transform.rotate(360-mHeading);
_transform.translate(-_path.boundingRect().width()/2, -_path.boundingRect().height()/2);
return _transform.map(_path);
}
void projPaint(QPainter* painter)
{
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::TextAntialiasing, true);
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
painter->setBrush(QBrush(mColor));
painter->setPen(QPen(QBrush(Qt::black), 1));
painter->setFont(mFont);
QPainterPath _path = projShape();
painter->drawPath(_path);
}
Unluckly I still suffer the minor issue with text fill mode:
I would like to have a solid black fill for the text instead of the mColor fill I use for the glyph/polygon.
I want to set an image into an imageView. On portrait orientation it works properly. But when the device has landscape orientation it does not load the image.
The strange thing is, once I rotate it to portrait and back to landscape it shows the image properly.
private void setPhoto(File photoFile) {
readyToDelete=false;
try {
Transformation transformation = new RoundedTransformationBuilder()
.borderColor(Color.parseColor("#757575"))
.borderWidthDp(3)
.cornerRadiusDp(15)
.oval(false)
.build();
Picasso.with(this)
.load(photoFile)
.fit()
.centerInside()
.transform(transformation)
.into(imageView);
imageView.setVisibility(View.VISIBLE);
deleteImageTextView.setVisibility(View.VISIBLE);
addImageTextView.setVisibility(View.GONE);
editScrollView.invalidate();
}
Seems you are running out of memory while loading the image, when in landscape the image is bigger to fit the view.
Try this:
Picasso picasso = new Picasso.Builder(image.getContext())
.listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception)
{
Log.e(TAG, "Picasso error:"+exception.getCause().getMessage()+"\n"+uri);
}
})
.build();
then use the picasso instance:
picasso.load(photoFile)....
I recommend you to use a listener when loading, if you have an error, just load the image resizing it to lower resolution, half the screen size for example, let screenSize be the size in pixels of the device screen largest axis:
picasso.load(photoFile).....into(_imageView, new Callback.EmptyCallback(){
#Override
public void onError()
{
picasso.load(photoFile).resize(screenSize/2, screenSize/2).centerInside().transform(transformation).into(imageView);
}
});
anyway the log you get on your listener will give you the clue of what's happening
I want to make a paint game in andengine. There is my codes. How can i use them in andengine? Or is there anything like drawPath in andengine? I tried to add Rects or Lines for drawing but my FPS was 10-15.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundColor(Color.WHITE);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
There are several ways to accomplish what you want.
create Rectangles (not lines since they differ from device to device) and add them to the scene to get a path. Use object pools to reuse your objects (Rectangles).
if the first approach doesn't perform well then you could also draw directly on an empty texture using canvas.
there is a class called RenderTexture on which you can draw entities. Use such a RenderTexture and draw your lines to it. create a sprite using this Texture and add it to the scene.
Could someone tell me how to catch this event?
Because when I rotated the phone to landscape mode, the app could not display correctly.
Thanks,
Duy
When this happens then BB UI framework definitelly calls layout(int width, int height) for your screen. This is because MainScreen is also a Manager, so it should layout all its child fields before BB UI framework starts painting.
So in layout() you could track current orientation state (with net.rim.device.api.system.Display.getOrientation()) and compare with the previous one. If it is changed, then the device has just been rotated.
I've come up with a method different to the suggested by Arhimed and it seems to work well (I use it to draw a custom Field differently - when the device is tilted). I have a method
protected void myOrientation() {
// portrait is true when dh > dw
boolean portrait = (Display.getOrientation() == Display.ORIENTATION_PORTRAIT);
// dw and dh = real horizontal and vertical dimensions of display - regardless of device orientation
int dw = portrait ? Math.min(Display.getWidth(), Display.getHeight()) : Math.max(Display.getWidth(), Display.getHeight());
int dh = portrait ? Math.max(Display.getWidth(), Display.getHeight()) : Math.min(Display.getWidth(), Display.getHeight());
// here I draw my custom Field
invalidate();
}
and call it once in the constructor and after that it is called on every Accelerometer event:
public class MyScreen extends MainScreen implements AccelerometerListener {
private MyScreen() {
if (AccelerometerSensor.isSupported()) {
orientationChannel = AccelerometerSensor.openOrientationDataChannel( Application.getApplication() );
orientationChannel.addAccelerometerListener(this);
}
....
}
public void onData(AccelerometerData accData) {
if (old != accData.getOrientation()) {
myField.myOrientation();
}
}
Maybe this helps you and yes - you have to check, if the keyboard is slided out on Torch
Regards
Alex