I've followed some forums and I'm lost with this problem:
I have a Custom View that draws 9 circles for me as shown below:
This circles must be an icon to the main one and 8 images for the others and it must be a drawable resource (I have png pictures in on my drawable folder).
How may I proceed to set this drawable images instead of the colors?
This is my actual code:
public class CircleView extends View {
public static interface IMenuListener{
public void onMenuClick(MenuCircle item);
}
public static class MenuCircle{
private int x,y,radius;
public int id;
public String text;
}
private Paint mainPaint;
private Paint secondPaint;
private Paint textPaint;
private int radius_main =130;
private int menuInnerPadding = 40;
private int radialCircleRadius = 60;
private int textPadding = 25;
private double startAngle = - Math.PI/2f;
private ArrayList<MenuCircle> elements;
private IMenuListener listener;
public void setListener(IMenuListener listener){
this.listener = listener;
}
public void clear(){
elements.clear();
listener=null;
}
public CircleView(Context context) {
super(context);
init();
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
elements = new ArrayList<>();
}
public void addMenuItem(String text,int id){
MenuCircle item = new MenuCircle();
item.id = id;
item.text=text;
elements.add(item);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
mainPaint = new Paint();
mainPaint.setColor(Color.DKGRAY); //color of main circle
secondPaint = new Paint();
secondPaint.setColor(Color.DKGRAY); // color of 8 circles
textPaint = new Paint();
textPaint.setColor(Color.BLACK); // text under 8 circles
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centerX = canvas.getWidth()/2 ;
int centerY= canvas.getHeight()/2;
canvas.drawCircle(centerX,centerY,radius_main,mainPaint);
for(int i=0;i<elements.size();i++){
double angle =0;
if(i==0){
angle = startAngle;
}else{
angle = startAngle+(i * ((2 * Math.PI) / elements.size()));
}
elements.get(i).x = (int) (centerX + Math.cos(angle)*(radius_main+menuInnerPadding+radialCircleRadius));
elements.get(i).y = (int) (centerY + Math.sin(angle)*(radius_main+menuInnerPadding+radialCircleRadius));
canvas.drawCircle( elements.get(i).x,elements.get(i).y,radialCircleRadius,secondPaint);
float tW = textPaint.measureText(elements.get(i).text);
canvas.drawText(elements.get(i).text,elements.get(i).x-tW/2,elements.get(i).y+radialCircleRadius+textPadding,textPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN){
for(MenuCircle mc : elements){
double distance = Math.hypot(event.getX()-mc.x,event.getY()-mc.y);
if(distance<= radialCircleRadius){
//touched
if(listener!=null)
listener.onMenuClick(mc);
return true;
}
}
}
return super.onTouchEvent(event);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
}
}
Related
I have created my custom View in Android and trying to draw a circle in that but nothing is drawing but with no errors.
Here is my code
public class ColorOptionsView extends RelativeLayout {
private View mValue;
private ImageView mImage;
private Paint paint;
String cirlceText;
int circleColor,circleTextColor;
float circleTextSize;
public ColorOptionsView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorOptionsView, 0, 0);
try {
cirlceText = a.getString(R.styleable.ColorOptionsView_circleText);
circleColor = a.getColor(R.styleable.ColorOptionsView_circleColor, 0);
circleTextColor = a.getColor(R.styleable.ColorOptionsView_circleTextColor, 0);
circleTextSize = a.getFloat(R.styleable.ColorOptionsView_circleTextSize,20);
} finally {
a.recycle();
}
}
public void setCirlceText(String cirlceText) {
this.cirlceText = cirlceText;
invalidate();
requestLayout();
}
public void setCircleColor(int circleColor) {
this.circleColor = circleColor;
invalidate();
requestLayout();
}
public void setCircleTextColor(int circleTextColor) {
this.circleTextColor = circleTextColor;
invalidate();
requestLayout();
}
public void setCircleTextSize(float circleTextSize) {
this.circleTextSize = circleTextSize;
invalidate();
requestLayout();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setColor(circleColor);
int centerX = this.getMeasuredWidth()/2;
int centerY = this.getMeasuredHeight()/2;
int raduis = 150;
canvas.drawCircle(centerX,centerY,raduis,paint);
paint.setColor(circleTextColor);
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(cirlceText,centerX,centerY,paint);
canvas.drawLine(0,100,100,0,paint);
}
I am not getting where I went wrong. Devs check it and help me out.
the idea is, i want to make animated kanji letter (in sequence) like this project HTML5 Stroke Animation. And my problem is, when i call onDraw method my canvas just draw simultaneously. I couldn't find much info about it on the internet, so any clue would be much appreciated if you have already come across the same situation.
here is my code:
public class MainActivity extends AppCompatActivity {
private TextView txt;
private SvgPathParser svgPathParser;
private PathView pathView;
private String sPath =
"M32.49,17.39c0.14,1.08,0.24,2.44-0.12,3.77c-2.29,8.41-11.14,24.16-21.81,35.56" +
"|M25.03,42c0.59,0.61,0.76,1.97,0.76,3.23c0,10.08,0.08,28.85,0,40.77c-0.02,3.48-0.04,6.4-0.04,8.38" +
"|M55.1,14.25c0.05,0.65,0.16,1.69-0.09,2.6c-1.55,5.6-8.51,16.02-17.36,24.43" +
"|M53.88,27.02c0.94,0.18,3.7,0.29,4.62,0.18c4.47-0.52,18.49-2.45,26.44-3.62c2.43-0.36,4.03-0.45,6.45-0.17" +
"|M52.82,39.44c1.03,0.85,1.4,3.75,0.72,5.89c-3.37,10.67-6.4,19.7-11.35,30.04c-1.45,3.03-0.49,4.25,1.47,4.33c10.84,0.43,18.96,1.05,29.44,3.78c5.98,1.55,12.27,4.02,17.89,7.93" +
"|M54.69,42.07c6.68-0.95,22.21-3.14,26.69-3.43c3.45-0.22,4.43,1.81,4.14,4.54c-1.33,12.48-5.94,37.8-10.23,47.46c-2.3,5.17-4.97,4.12-7.54,1.33" +
"|M68.32,43.35c0.45,0.88,0.63,2.39,0.13,4.22c-2.32,8.56-7.53,25.28-10.01,32.34" +
"|M32.07,61.64c3.43,0.61,5.94,0.44,8.42,0.17c12.25-1.31,31.7-3.07,49-3.92c2.76-0.14,5.75-0.41,8.43,0.38";
String[] arrayPath = sPath.split("\\|");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new PathView(this));
}
private Path path(String sPath) throws ParseException {
svgPathParser = new SvgPathParser();
return svgPathParser.parsePath(sPath);
}
public class PathView extends View {
Path path;
Paint paint;
List<Path> paths;
float length;
public PathView(Context context) {
super(context);
init();
}
public PathView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void init() {
paths = new ArrayList<>();
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
for (int i = 0; i < arrayPath.length; i++) {
try {
paths.add(path(arrayPath[i]));
// path = );
} catch (ParseException e) {
e.printStackTrace();
}
}
// Measure the path
for (Path path : paths) {
this.path = path;
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(2000);
animator.start();
}
}
//is called by animtor object
public void setPhase(float phase) {
Log.d("pathview", "setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private PathEffect createPathEffect(float pathLength, float phase, float offset) {
return new DashPathEffect(new float[]{pathLength, pathLength},
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c) {
super.onDraw(c);
for (Path path : paths) {
this.path = path;
c.drawPath(path, paint);
}
}
}
}
I am trying to add a simple selector to an object - imageView - which is an instance of a class which extends imageview.
final PackageTypeView ptv = packageTypeViewsList.get(index);
index++;
Drawable drawable = getResources().getDrawable(
R.drawable.selector);
ImageTitleView imageView = new ImageTitleView(
getActivity());
imageView.setImageBitmap(BeanUtils.decodeSampledBitmapFromResource(new File(ptv.getTileRenderPath()), screenWidth, screenWidth));
if (ptv.getTitleBgArgb() != null) {
imageView.setColorCode(ptv.getTitleBgArgb());
}
imageView.setImageDrawable(drawable);
//TODO check this entry in the database
if (ptv.isShowingTitle()) {
imageView.setDescription(ptv.getName());
}
imageView.setScaleType(ScaleType.CENTER_CROP);
imageView.setClickable(true);
// imageView.setImageResource(R.drawable.selector);
imageView.setOnClickListener(this);
imageView.setTag(ptv.getId());
and here is the ImageTitleView class.
public class ImageTitleView extends ImageView {
private String description;
private String colorCode = "aaaaaaBB";
private static float fontSize = -1;
private Paint paint = new Paint();
private Rect rect = new Rect();
private Bitmap bitmap = null;
private static Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);
public ImageTitleView(Context context, Bitmap bitmap) {
super(context);
initPaint(context);
this.bitmap = bitmap;
}
public ImageTitleView(Context context) {
super(context);
initPaint(context);
}
public ImageTitleView(Context context, String description) {
super(context);
this.description = description;
initPaint(context);
}
public ImageTitleView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint(context);
}
public ImageTitleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPaint(context);
}
private void initPaint(Context context) {
fontSize = context.getResources().getDimension(R.dimen.text_size_grid_info);
paint.setTextSize(fontSize);
paint.setTypeface(tf);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (description != null) {
rect.set(new Rect(0, canvas.getHeight() - (canvas.getHeight() / 4), canvas.getWidth(), canvas.getHeight()));
paint.setColor(Color.parseColor("#" + colorCode));
canvas.drawRect(rect, paint);
float y = rect.top + ( (rect.bottom - rect.top) / 2 + fontSize / 2);
paint.setColor(Color.WHITE);
canvas.drawText(description, 15, y, paint);
}
}
The problem is the the following when I add the selector the imageView's bitmap is replaced with
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getColorCode() {
return colorCode;
}
public void setColorCode(String colorCode) {
if (colorCode != null && !colorCode.isEmpty()) {
this.colorCode = colorCode;
}
}
#Override
public void setClickable(boolean clickable) {
super.setClickable(clickable);
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
}
}
and here is the selector:
<item android:state_pressed="true" android:drawable="#color/button_pressed_color"/>
<item android:state_focused="true" android:drawable="#color/button_pressed_color"/>
<item android:drawable="#android:color/transparent"/>
The problem is that the selector change the background of the imageView object and replace the bitmap from this object with a transparent background.
I have following TextView
public class Cube extends TextView {
Context mContext;
Drawable background;//Hintergrund des Blocks
char mLetter;//Buchstabe des Blocks
int x, y;//Koordinaten des Blocks
#SuppressWarnings("deprecation")
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public Cube(Context context, char letter, int _x, int _y) {
super(context);
mContext = context;
mLetter = letter;
background = ContextCompat.getDrawable(getContext(), R.drawable.cube);
x = _x;
y = _y;
this.setText("" + letter);
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN)
this.setBackgroundDrawable(background);
else
this.setBackground(background);
}
public void drawCube(Canvas canvas){//how to draw now!? This is called from a separate thread in SurfaceView
}
}
If I call following in drawCube():
background.setBounds(x, y, x + 20, y + 20);
background.draw(canvas);
it just draws the backgroundDrawable. But how can I draw it with the text/the letter inside? That it looks like this: (The background ist the canvas, the orange and white one is the Background and the "A" is the letter/text)
EDIT: Code at 21.09
This is my (shortened) thread:
public class CanvasThread extends Thread {
private SurfaceHolder mSh;
private ArrayList<Cube> mCubes;
private Canvas mCanvas;
private Context mContext;
private boolean mRun = false;
private boolean mDown = false;
private boolean newCube = false;
public CanvasThread(SurfaceHolder sh, Context context){
mSh = sh;
mCubes = new ArrayList<>();
mContext = context;
}
public void run(){
while(mRun){
mCanvas = null;
try{
mCanvas = mSh.lockCanvas(null);
synchronized (mSh){
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
newCube = true;
for(int i = 0; i < mCubes.size(); i++){
if(mCubes.get(i).getSpeed() > 0)
newCube = false;
if(mDown) {
if (mCubes.get(i).moveDown(feld)) {
mDown = false;
}
}
//mCubes.get(i).invalidate();
//mCubes.get(i).requestLayout();
mCubes.get(i).draw(mCanvas);
}
if(newCube)
addCube();
}
} finally {
if(mCanvas != null){
mSh.unlockCanvasAndPost(mCanvas);
}
}
}
}
public void addCube(){
Random r = new Random();
Cube cube = new Cube(mContext, mBuchstaben[r.nextInt(29)], r.nextInt(10), 0, mCanvas);
mCubes.add(cube);
}
}
This is my (shortened) fragment which uses the canvas/surface view:
public class KlassischFragment extends Fragment implements SurfaceHolder.Callback {
SurfaceHolder sh;
SurfaceView sv;
private CanvasThread thread;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_klassisch, container, false);
sv = (SurfaceView) view.findViewById(R.id.surfaceView);
sh = sv.getHolder();
sh.addCallback(this);
sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
return view;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread = new CanvasThread(sh, getContext());
thread.setRunnable(true);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
//thread.setRunnable(false);
while(retry){
try{
thread.join();
retry = false;
} catch(InterruptedException ie){
//Immer wieder versuchen
}
break;
}
thread = null;
}
}
Here is an example on how to draw a text on top of a square. Some of the values hardcoded but you should be able to make them dynamic.
public class Cube extends View {
private final static String TEST_STRING = "ABC";
private Paint mBackgroundPaint;
private Paint mTextPaint;
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public Cube(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public Cube(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public Cube(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public Cube(Context context) {
this(context, null, -1);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Just for demo purposes this should be calculated properly
int desiredWidth = 100;
int desiredHeight = 100;
setMeasuredDimension(desiredWidth, desiredHeight);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int savedCount = canvas.save();
drawRectangle(canvas);
drawText(canvas);
canvas.restoreToCount(savedCount);
}
private void init() {
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(Color.BLUE);
mBackgroundPaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
// This need to be adjusted based on the requirements that you have
mTextPaint.setTextSize(20.0f);
}
private void drawRectangle(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundPaint);
}
private void drawText(Canvas canvas) {
Rect rect = new Rect();
// For simplicity I am using a hardcoded string
mTextPaint.getTextBounds(TEST_STRING, 0, 1, rect);
int w = getWidth(), h = getHeight();
float x = (w - rect.width()) / 2, y = ((h - rect.height()) / 2) + rect.height();
canvas.drawText(TEST_STRING, 0, 1, x, y, mTextPaint);
}
}
We have Android 3D Carousel here: http://www.codeproject.com/KB/android/androcarousel.aspx
There my problem is that: i want to make text label between the image and the reflection ?
how can i do it?
Help me please
I found the anwser: Use CarouselFrame
public class CarouselFrame extends FrameLayout implements Comparable<CarouselFrame> {
private int index;
private float currentAngle;
private float x;
private float y;
private float z;
private boolean drawn;
private ImageView image;
private TextView txt;
public CarouselFrame(Context context) {
this(context, null, 0);
}
public CarouselFrame(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CarouselFrame(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
image = new ImageView(context);
this.addView(image, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
txt = new TextView(context);
this.addView(txt, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}
public void setImageBitmap(Bitmap img){
image.setImageBitmap(img);
}
public void setText(String text){
txt.setText(text);
}
public void setIndex(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
public void setCurrentAngle(float currentAngle) {
this.currentAngle = currentAngle;
}
public float getCurrentAngle() {
return currentAngle;
}
public int compareTo(CarouselFrame another) {
return (int)(another.z - this.z);
}
public void setX(float x) {
this.x = x;
}
public float getX() {
return x;
}
public void setY(float y) {
this.y = y;
}
public float getY() {
return y;
}
public void setZ(float z) {
this.z = z;
}
public float getZ() {
return z;
}
public void setDrawn(boolean drawn) {
this.drawn = drawn;
}
public boolean isDrawn() {
return drawn;
}
}