Custom Circular TextView - Text Not Centered in Circle - java

I put together a TextView class utilizing some different suggestions I've seen and wrote this class to display a TextView inside of a circle. The circle comes out great, but the text appears slightly above the center of the circle.
I can't figure out what's causing this. Here's my code:
CircularTextView
public class CircularTextView extends AppCompatTextView {
private ShapeDrawable backgroundDrawable;
private OvalShape ovalShape;
private int backgroundColor;
public CircularTextView(Context context) {
super(context);
backgroundColor = ContextCompat.getColor(context, R.color.color_circle_test_solid);
allocateShapes();
}
public CircularTextView(Context context, AttributeSet attrs) {
super(context, attrs);
backgroundColor = ContextCompat.getColor(context, R.color.color_circle_test_solid);
allocateShapes();
}
public CircularTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
backgroundColor = ContextCompat.getColor(context, R.color.color_circle_test_solid);
allocateShapes();
}
//Source https://stackoverflow.com/questions/25203501/android-creating-a-circular-textview/34685568#34685568
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int h = this.getMeasuredHeight();
int w = this.getMeasuredWidth();
int r = Math.max(w, h);
setMeasuredDimension(r, r);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
backgroundDrawable.setShape(ovalShape);
backgroundDrawable.getPaint().setColor(backgroundColor);
setBackground(backgroundDrawable);
}
private void allocateShapes(){
backgroundDrawable = new ShapeDrawable();
ovalShape = new OvalShape();
}
public void setBackgroundColor(int color){
backgroundColor = color;
invalidate();
}
}
TestCircleTextViewActivity
public final class TestCircleTextViewActivity extends BaseActivity {
#BindView(R.id.circle_text)
CircularTextView circleText;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_circular_textview);
ButterKnife.bind(this);
int circleColor = ContextCompat.getColor(this, R.color.color_circle_test_solid);
circleText.setBackgroundColor(circleColor);
}
}
activity_test_circular_textview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.thinkbubble.app.ui.view.CircularTextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/circle_text"
android:layout_gravity="center"
android:layout_centerInParent="true"
android:padding="4dp"
android:text="Keyword">
</com.thinkbubble.app.ui.view.CircularTextView>
</RelativeLayout>

Use android:gravity="center" for you TextView to make text center in circle

Related

RecyclerView Android Dynamic Height

I am looking at creating dynamic heights in my RecyclerView to be responsive across all devices. Currently this works fine but for the first two rows at the start I have a double cell and the height of these two rows gets set to the first cell. I want instead this cell on both the first and second row to match the height of the last cell and become a rectangle. I have tried a few ways but none seem to work I am not sure where the problem is but I hope someone can show me. I will attach screenshots and the code below.
SquareLayout.java
public class SquareLayout extends LinearLayout {
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int width, int height) {
// int width = MeasureSpec.getSize(widthMeasureSpec);
//int height = MeasureSpec.getSize(heightMeasureSpec);
// note we are applying the width value as the height
//if(width>=370){
// super.onMeasure(widthMeasureSpec, widthMeasureSpec/2);
// }
// else{
// super.onMeasure(widthMeasureSpec, widthMeasureSpec);
// }
super.onMeasure(width, width);
// Log.d("int","int is: "+ width);
}
}
DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<AndroidVersion> android;
private Context context;
public DataAdapter(Context context,ArrayList<AndroidVersion> android) {
this.android = android;
this.context = context;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
// int width = viewHolder.tv_android.getMeasuredWidth() / 2; //returns -1
Log.d("MYINT", "value: " + i);
//Picasso.with(context).load(android.get(i).getAndroid_image_url()).resize(240, 120).into(viewHolder.img_android);
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private LinearLayout testheight;
private ImageView img_android;
public ViewHolder(View view) {
super(view);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private final String android_version_names[] = {
"test1",
"test2",
"test3",
"test4",
"test5",
"test6",
"test7",
"test8",
"test9",
"test10"
};
private final String android_image_urls[] = {
"http://example.com/images/test.png",
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),3);
ArrayList<AndroidVersion> androidVersions = prepareData();
((GridLayoutManager) mLayoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (position == 0 || position == 2) {
return 2; // ITEMS AT POSITION 1 AND 6 OCCUPY 3 SPACES
}
else {
return 1; // OTHER ITEMS OCCUPY ONLY A SINGLE SPACE
}
}
});
recyclerView.setLayoutManager(mLayoutManager);
DataAdapter adapter = new DataAdapter(getApplicationContext(), androidVersions);
recyclerView.setAdapter(adapter);
}
private ArrayList<AndroidVersion> prepareData(){
ArrayList<AndroidVersion> android_version = new ArrayList<>();
for(int i=0;i<android_version_names.length;i++){
AndroidVersion androidVersion = new AndroidVersion();
androidVersion.setAndroid_version_name(android_version_names[i]);
androidVersion.setAndroid_image_url(android_image_urls[i]);
android_version.add(androidVersion);
}
return android_version;
}
}
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<example.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:background="#color/reloadedpurple"
android:elevation="6dp"
android:orientation="vertical">
<ImageView
android:id="#+id/img_android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<TextView
android:id="#+id/tv_android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</LinearLayout>
</example.SquareLayout>

How to add delay in onDraw() in android canvas?

I am making a project. It draws concentric circles in android canvas. When the user drags the screen, all the circles move accordingly. Here is my code so far.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="#android:color/white">
<RelativeLayout
android:id="#+id/scrollableSpace"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true">
<project.myProject.DrawOrbit
android:id="#+id/orbitsRegion"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
</RelativeLayout>
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnTouchListener
{
PointF center;
center.x=500;center.y=500;
float radius[]={100,200,300,400,500};
DrawOrbit orbit;
int startX=0,startY=0,currentX=0,currentY=0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout layout=(RelativeLayout)findViewById(R.id.scrollableSpace);
orbit.draw(center,radius);
layout.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent motionEvent)
{
final int action= motionEvent.getAction();
switch(action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
{
startX=(int)motionEvent.getRawX();
startY=(int)motionEvent.getRawY();
break;
}
case MotionEvent.ACTION_MOVE:
{
currentX=(int)motionEvent.getRawX();
currentY=(int)motionEvent.getRawY();
float diffX=currentX-startX;
float diffY=currentY-startY;
startX=currentX;
startY=currentY;
center.x+=diffX;
center.y+=diffY;
orbit.draw(center,radius);
break;
}
}
return true;
}
}
DrawOrbit.java
public class DrawOrbit extends View
{
PointF center;
float radius[];
public DrawOrbit(Context context) {
super(context);
}
public DrawOrbit(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public DrawOrbit(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
int len=radius.length;
for(int a=0;a<len;a++)
{
canvas.drawCircle(center.x,center.y,radius[a],paint);
}
}
public void draw(PointF center, float radius[])
{
this.center=center;
this.radius=radius;
invalidate();
requestLayout();
}
}
What I want to do is that the circles should appear one by one. First the inner most circle then the next one after some delay then the next and so on. The same effect should be seen when the screen is dragged. How can I achieve this? Any help will be appreciated.
What you're looking for is a timeout. I'd suggest creating a new thread to draw everything, and start by drawing the first circle, have the method look like this:
public void drawCircle() {
//Draw logic
TimeUnit.SECONDS.sleep(3);
drawNextCircle();
}
//Assuming on java 1.8+
Thread thread = new Thread() => {
drawCircle();
}
What this will do is have the thread sleep for 3 seconds, and then continue normal operation after the time period is up. You can change it to other measurements of time such as TimeUnit.MILLISECONDS or TimeUnit.MINUTES as well.
edit: You likely won't want this in your main thread, as it will stop the ENTIRE application from working for however long you put the thread on timeout, so it's almost essential for this to work that you put it in a separate thread.
edit 2: It would make more sense to add a separate util method to timeout and then call another method via reflection than the above code, but the same code would be needed.
Figured out the answer to my own question. I had to use a Handler, multiplied the delay with the for-loop variable and made 1 then 2 then so on.. circles to get the desired effect. Here is the code.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnTouchListener
{
PointF center;
center.x=500;center.y=500;
float radius[]={100,200,300,400,500};
DrawOrbit orbit;
int startX=0,startY=0,currentX=0,currentY=0;
Handler handler1 = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout layout=(RelativeLayout)findViewById(R.id.scrollableSpace);
for (int a = 0; a<radius.length ;a++)
{
final int index=a;
handler1.postDelayed(new Runnable() {
#Override
public void run() {
orbit.draw(center,radius,index);
}
}, 300 * a);
}
layout.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent motionEvent)
{
final int action= motionEvent.getAction();
switch(action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
{
startX=(int)motionEvent.getRawX();
startY=(int)motionEvent.getRawY();
break;
}
case MotionEvent.ACTION_MOVE:
{
currentX=(int)motionEvent.getRawX();
currentY=(int)motionEvent.getRawY();
float diffX=currentX-startX;
float diffY=currentY-startY;
startX=currentX;
startY=currentY;
center.x+=diffX;
center.y+=diffY;
break;
}
case MotionEvent.ACTION_UP:
{
for (int a = 0; a<radius.length ;a++)
{
final int index=a;
handler1.postDelayed(new Runnable() {
#Override
public void run() {
orbit.draw(center,radius,index);
}
}, 300 * a);
}
break;
}
}
return true;
}
}
DrawOrbit.java
public class DrawOrbit extends View
{
PointF center;
float radius[];
int index;
public DrawOrbit(Context context) {
super(context);
}
public DrawOrbit(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public DrawOrbit(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
int len=radius.length;
for(int a=0;a<index;a++)
{
canvas.drawCircle(center.x,center.y,radius[a],paint);
}
}
public void draw(PointF center, float radius[],int index)
{
this.center=center;
this.radius=radius;
this.index=index;
invalidate();
requestLayout();
}
}

Why is the onDraw Not Being Called in Custom View for Android?

I am developing in Android Canvas.
But the onDraw() has not called after invalidate();
In the layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.wen.MainActivity">
<com.wen.Drawpath_view
android:id="#+id/view_path"
android:layout_weight="0.7"
android:layout_width="match_parent"
android:layout_height="0dp"/>
<RelativeLayout
android:layout_weight="0.3"
android:layout_width="match_parent"
android:layout_height="0dp">
<Button
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
In the MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private Drawpath_view View_path;
private Button test_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View_path = findViewById(R.id.view_path);
View_path = new Drawpath_view(MainActivity.this);
test_btn = findViewById(R.id.test);
test_btn.setOnClickListener(this);
View_path.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
View_path.getViewTreeObserver().removeOnPreDrawListener(this);
View_path.setMinimumHeight(View_path.getHeight());
View_path.setMinimumWidth(View_path.getWidth());
return true;
}
});
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.test){
View_path.Testdraw();
}
}
}
In the customer View.
public class Drawpath_view extends View {
private static final String TAG = "view";
private Paint paint;
private Path path = new Path();
public Drawpath_view(Context context) {
super(context);
setWillNotDraw(false);
initView();
}
public Drawpath_view(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void initView() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(3);
}
public void Testdraw(){
Log.d(TAG,"draw");
path.moveTo(60,60);
path.lineTo(460,460);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Log.d(TAG,"onDraw");
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
}
When I click the button in Activity. It will call
View_path.Testdraw();
But the onDraw in Drawpath_view has not been called. Did I missing something ?
Thanks in advance.
You can remove View_path = new Drawpath_view(MainActivity.this); from your code,
as you already attached view in xml.
By default all ViewGroup sub-classes do not call their onDraw method, you will enable it by calling setWillNotDraw(false) on View_path.
Add setWillNotDraw(false); initView();
into the second constructor as well.

Drawing a Path with multiple colors

I am drawing on android.graphics.Canvas using android.graphics.Path. I want to allow the user to draw using a range of colors and stroke widths, however, whenever the color or stroke width is changed, everything is re-drawn using the new color or stroke width. How can I fix this?
xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/btnW10"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width10"/>
<Button
android:id="#+id/btnW40"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width40"/>
<Button
android:id="#+id/btnW70"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:text="Width70"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="20dp"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="#+id/btnBlue"
android:text="Blue"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="#+id/btnRed"
android:text="Red"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="3sp"
android:layout_weight="1"
android:id="#+id/btnGreen"
android:text="Green"/>
</LinearLayout>
<com.vladislav.canvaswc.DrawLine
android:id="#+id/drwLine"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
main.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
DrawLine dr;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnB=(Button) findViewById(R.id.btnBlue);
Button btnG=(Button) findViewById(R.id.btnGreen);
Button btnR=(Button) findViewById(R.id.btnRed);
Button btnW10=(Button) findViewById(R.id.btnW10);
Button btnW40=(Button) findViewById(R.id.btnW40);
Button btnW70=(Button) findViewById(R.id.btnW70);
dr =(DrawLine) findViewById(R.id.drwLine);
btnB.setOnClickListener(this);
btnG.setOnClickListener(this);
btnR.setOnClickListener(this);
btnW10.setOnClickListener(this);
btnW40.setOnClickListener(this);
btnW70.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.btnBlue : dr.changeColor(Color.BLUE);break;
case R.id.btnGreen : dr.changeColor(Color.GREEN);break;
case R.id.btnRed : dr.changeColor(Color.RED);break;
case R.id.btnW10 : dr.changeWidth(10f);break;
case R.id.btnW40 : dr.changeWidth(40f);break;
case R.id.btnW70 : dr.changeWidth(70f);break;
}
}
}
drawline.java ChangeWidthColor its my interface with 2 methods changeColor()
and changeWidth()
public class DrawLine extends View implements ChangeWidthColor {
private Paint paint = new Paint();
private Path path = new Path();
public float x;
public float y;
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
//paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
//paint.setStrokeWidth(5f);
}
#Override
public void changeColor(int color) {
paint.setColor(color);
}
#Override
public void changeWidth(float width) {
paint.setStrokeWidth(width);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x= event.getX();
y= event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x= event.getX();
y= event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
invalidate();
break;
}
invalidate();
return true;
}
}
This solution maintains a List of Path objects and a List of Integers for storing colors. These Lists are in parallel - 1 entry in each list for a Path and color pair. onDraw iterates these Lists, drawing each Path with the corresponding color.
Each time the user clicks to change the color, a new Path is created. ACTION_DOWN and ACTION_MOVE call moveTo(x,y) and lineTo(x,y) on the path, and ACTION_UP causes the Path and current color to be added to the lists.
Note: I have not implemented a solution for stroke width, however, you should be able to follow the example and add this yourself.
public class DrawLine extends View {
private Path path = new Path();
private Paint paint = new Paint();
private int currentColor = Color.BLACK;
private List<Path> paths = new ArrayList<Path>();
private List<Integer> colors = new ArrayList<Integer>();
private float x;
private float y;
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setColor(currentColor);
}
public void changeColor(int color) {
currentColor = color;
path = new Path();
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int x = 0; x < paths.size(); x++) {
paint.setColor(colors.get(x));
canvas.drawPath(paths.get(x), paint);
}
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
paths.add(path);
colors.add(currentColor);
invalidate();
break;
}
invalidate();
return true;
}
}
`
public class DrawLine extends View implements ChangeWidthColor {
private Path path = new Path();
private Paint paint = new Paint();
private int currentColor = Color.BLACK;
private float width = 1f;
public float x;
public float y;
private LinkedList<Integer> color = new LinkedList<Integer>();
private LinkedList<Float> widthSize = new LinkedList<Float>();
private LinkedList<Path> paths = new LinkedList<Path>();
public DrawLine(Context context) {
super(context);
init(context);
}
public DrawLine(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DrawLine(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setColor(currentColor);
paint.setStrokeWidth(5f);
}
#Override
public void changeColor(int color) {
currentColor = color;
path = new Path();
}
#Override
public void changeWidth(float width) {
this.width = width;
path = new Path();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < paths.size(); i++) {
paint.setStrokeWidth(widthSize.get(i));
paint.setColor(color.get(i));
canvas.drawPath(paths.get(i), paint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
color.add(currentColor);
paths.add(path);
widthSize.add(width);
break;
default:
return false;
}
invalidate();
return true;
}
}
you need to call invalidate() inside your custom view whenever you are modifying something related to UI. so updated methods will be:
#Override
public void changeColor(int color) {
paint.setColor(color);
invalidate();
}
#Override
public void changeWidth(float width) {
paint.setStrokeWidth(width);
invalidate();
}

Scaling ImageButton basing on screen size

In my application i can scaling an ImageView using this class
`public class resizeAvatar extends View {
private final Drawable sfondoAvatar;
public resizeAvatar(Context context) {
super(context);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs) {
super(context, attrs);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
#Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * sfondoAvatar.getIntrinsicHeight() / sfondoAvatar.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
`
And writing in the layout:
<com.myapp.app.resizeAvatar
android:id="#+id/mainvoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_centerVertical="true"/>
But in this way i can't have the onClick event.. i need do the same but using an ImageButton.. Is there a way?
In the activity where you include this view and in the onCreate method do the following:
resizeAvatar myMainvoice = (resizeAvatar) v.findViewById(R.id.mainvoice);
myMainVoice.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
//place your on click logic here
}
});

Categories