I am trying to make a gaze tracking in android studio. And I am trying to draw on screen a rectangle to the corresponding point of gaze. But my method doesn't work. I don't have any experience in drawing in android studio.
This is my draw class
public class drawMargins extends View {
Paint paint;
private volatile Margin margin;
public drawMargins(Context context) {
super(context);
init(null);
}
public drawMargins(Context context, AttributeSet attrs)
{
super(context, attrs);
init(attrs);
}
public drawMargins(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public void updateMargin(Margin margin2) {
margin = margin2;
postInvalidate();
}
private void init(#Nullable AttributeSet set)
{
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (margin==null)
return;
paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRect(
(float)((canvas.getWidth()/8)*margin.getX()),
(float)((canvas.getHeight()/8)*margin.getY()),
(float)((canvas.getWidth()/8)*margin.getX()+canvas.getWidth()/8),
(float)((canvas.getHeight()/8)*margin.getY()+canvas.getHeight()/8),paint);
}
}
and this is how I find the viewbyid("Draw") and update the vars:
DrawMargins = (drawMargins)LayoutInflater.from(context).inflate(R.layout.activity_live_preview,null).findViewById(R.id.Draw);
Margin eyeNose = new Margin(marginX(),marginY());
Margin drawOnScreen = onScreen(correspondingOnScreen(eyeNose,NEMargin,SEMargin,SWMargin,NWMargin,0),0,8,0,8,0 );
DrawMargins.updateMargin(drawOnScreen);
Should I call the draw method? With what canvas?
Try calling invalidate() instead of postInvalidate() in updateMargins(). This will call draw() and should draw the rectangle.
I would suggest you do one step at a time. I don't know exactly how you have your Activity or Fragment set, so I am just gonna go through that as well.
To keep things simple, let me assume that there is only Activity and no Fragments. You need two Java Class to get your objective accomplished: DrawMarginsActivity and DrawMargins.
DrawMargins is a Custom View. Custom views help you create your own custom drawing. Refer this for more details: https://developer.android.com/training/custom-views/custom-drawing . You need to override the onDraw(Canvas canvas) method. This method has the canvas parameter and you will be drawing on to this canvas.
Now you need to add DrawMargins view to your DrawMarginsActivity. You can do this by adding this view to your DrawMarginsActivity's layout file. Then you can get a reference to the DrawMargins view via findViewById().
Be default, when your Activity is created, the DrawMargins's onDraw() method will be called and it will render. But if you want to call the onDraw() again, you have to call DrawMargins.invalidate() method. This will invalidate the view and call the onDraw() method for you.
I am not sure on which action you want the view to draw. Based on that, you need to call the invalidate() method.
Related
I have View-based element in main activity and an image in drawable folder
public class MyView extends View {
private Bitmap mSprite;
public MyView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mSprite = BitmapFactory.decodeResource(getResources(), R.drawable.plank);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mSprite, 0.f, 0.f, null);
}
}
The image is displayed but looks blurry and too large (ref). How can I get the actual size of bitmap and draw in on canvas?
For anyone faced the above issue: just put your image in nodpi folder and it will match its actual size.
I am writing an app. One aspect of it is lines being drawn over an image. Here's the practice code I've been working with:
public class DrawView extends View {
Paint paint = new Paint();
private void init() {
paint.setColor(Color.BLACK);
}
public DrawView(Context context) {
super(context);
init();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
#Override
public void onDraw(Canvas canvas) {
paint.setStrokeWidth(20);
canvas.drawLine(100, 100, 20, 20, paint);
canvas.drawLine(20, 0, 0, 20, paint);
}
}
I want the Canvas to be fairly large, so I need people to be able to scroll in both directions (left/right and up/down). How do I accomplish this? I'm unfamiliar with the Canvas class so any help will be appreciated.
If you want to draw on canvas with your custom height and width you have to call setContentView(android.view.View yourView , android.view.Viewgroup.LayoutParam yourLayout) in your activity class.Because by default setContentView(View view) method use full width and height.So you have to use its overloaded method with two parameter along with your desired. See documentation for more info.And don`t use only LayoutParams() constructor to create its object. Use it by writing its full path like android.view.ViewGroup.LayoutParams. Because there are some other classes with same name in Android SDK.
MyView customView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
customView = new MyView(getApplicationContext());
android.view.ViewGroup.LayoutParams lp = new android.view.ViewGroup.LayoutParams(100,200);//100 is width and 200 is height
setContentView(customView, lp);
customView.setOnClickListener(this);
}`
So I have this DrawAnim.java class file and I want to use its content inside my MainAcitivty. I tried creating an object like this:
DrawAnim draw;
And in onCreate method, I did this:
draw.onDraw(); <- I know I have to pass a parameter but don't know what to pass on.
Here's my class:
public class DrawAnim extends View {
Bitmap ball;
int x, y;
public DrawAnim(Context context) {
super(context);
ball = BitmapFactory.decodeResource(getResources(), R.drawable.globe);
x=0;
y=0;
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
Rect ourRect = new Rect();
ourRect.set(0,0,canvas.getWidth(),canvas.getHeight()/2);
Paint red = new Paint();
red.setColor(Color.RED);
red.setStyle(Paint.Style.FILL);
canvas.drawRect(ourRect,red);
if( x < canvas.getWidth()) {
x += 10;
} else{
x =0;
}
if( y < canvas.getHeight()){
y+=10;
}else{
y =0;
}
Paint p = new Paint();
canvas.drawBitmap(ball,x,y,p);
invalidate();
}
}
You've extended a View, so you must use it like any other view, either by adding it programmatically at runtime or using it in a layout.
Here is how to add a view in the code. The following steps should be added to the onCreate method of the splash activity.
Get the Layout where the view will be added to in the code, something like LinearLayout linearLayout = findViewById(R.id.linearlayout); (It of course has to be change to your layout and layout-id)
Create an instance of the DrawAnim
Add it to the layout by linearLayout.addView(drawAnim);
Hope this gives an idea and helps.
Here is a link to an animated splashscreen and a link to a very simple splashscreen just to show some alternatives to adding a view. Although the 2nd one is very limited it has a bit animation and does not delay the start of your app.
You should add it like any other views, pass context to your custom view constructor, set Layout params and add it to the parent view group.
DrawAnim draw = new DrawAnim(this); // 'this' as a context in activity
draw.setLayoutParams(layoutParams);
parentViewGroup.addView(draw);
I am new to android and would like some assistance on rotating my relative layout for a two-player game I am working on. I have seen the posts here and have looked into many other posts on the same subject on SO. My first question is how to I call the new class I just made? For all the posts that dont just tell me to use android:rotation (which is not avaliable in 2.3-) I make a new class, but I get a notification that the class is never called. Do I call the class simmilar to how I call a method? Or is there some command in AndroidManifest? Finialy, how does the new class rotate only one Relative layout and not the other? I just would like to know how its supposted to work.
This is the new Class that I am supposted to make:
public class MyRelativeLayout extends RelativeLayout {
public MyRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyRelativeLayout(Context context) {
super(context);
init();
}
private void init() {
setStaticTransformationsEnabled(true);
}
#Override
protected boolean getChildStaticTransformation(View child, Transformation t) {
t.setTransformationType(Transformation.TYPE_MATRIX);
Matrix m = t.getMatrix();
m.reset();
m.postRotate(180, child.getWidth() / 2.0f, child.getHeight() / 2.0f);
return true;
Thanks for your help
In the oncreate() method in your activity do setContentView(new MyRelativeLayout(this))
I am struggling with the logic behind this, so any tips would be appreciated. I have two classes, one in which the fragment is created and one in which my custom view is created, and I am trying to do some animation. In the main layout, I have an edit text field and a button. What I want to do is to add to the custom view when a button is clicked, the text within the edit text will be added to the custom view. Thinking about HOW to do this, I am drawing a blank, and I am beginning to think it is not possible. Should I just create the edit text within the custom view? Here is the code showing what I am doing (but stuck on a next step, or whether or not I should scrap this approach and try a different one)
The main fragment
public class DestroyerView extends Fragment
{
private Context mContext;
Paint paint = new Paint();
private AnimatedNegative PositiveAnimatedNegative;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mContext = this.getActivity();
View view = inflater.inflate(R.layout.activity_destroyer, container, false);
final Button fire = (Button) view.findViewById(R.id.destroy);
PositiveAnimatedNegative = (AnimatedNegative) view.findViewById(R.id.anim_view);
fire.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
// logic here?
}
});
return view;
}
}
public AnimatedNegative(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = this.getContext();
h = new Handler();
mCalendarDbHelper=new CalendarDbAdapter(mContext);
mCalendarDbHelper.open();
}
private Runnable r= new Runnable()
{
#Override
public void run()
{
invalidate();
}
};
protected void onDraw (Canvas canvas)
{
String word = "This is a sentence";
paint.setColor(Color.parseColor("#1E90FF"));
paint.setStyle(Style.FILL);
canvas.drawPaint(paint);
paint.setColor(Color.BLACK);
paint.setTextSize(20);
x = this.getWidth()/2;
y = this.getHeight()/2;
canvas.drawText(word, x, y, paint);
}
}
... Now this would be much easier if I could reference the button inside of the custom view, but it doesn't seem I can do that, or if I could simply add to the custom view inside of the main activity class, but it doesn't seem that I can do that either (not without creating a new canvas, which seems to be doing too much for what it is that I want to do (just add the words)). So, finally, is the way I am currently trying to do this a dead end? Any help would be appreciated.
I think I got it. I'll call invalidate with the the AnimatedNegative object defined in my main activity, and then pass in the word from the edit text and a true value, so that I can check for it in the view and redraw. Added code shown below:
Within the main activity:
public void onClick(View arg0)
{
PositiveAnimatedNegative.invalidate();
PositiveAnimatedNegative.add = true;
PositiveAnimatedNegative.positive_word = "This is a positive word";
}
And within the custom view:
if (add == true)
{
canvas.drawText(positive_word, x,y, paint);
}