I am adding myCustomView in a linear layout multiple times, it is working fine for first instance of customView, but unable to add it multiple times.
Here is the Custom View class:
public class MultiTouchView extends View {
private float x, y;
Bitmap image;
public MultiTouchView(Context context, Bitmap image) {
super(context);
this.image = image;
// TODO Auto-generated constructor stub
}
public MultiTouchView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MultiTouchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(image, x, y, null);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch(action){
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
}
This is the class where i am adding custom view:
public class AndroidTouch extends Activity {
LinearLayout linear;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
linear = (LinearLayout)findViewById(R.id.linear);
Bitmap backgroundCard = BitmapFactory.decodeResource(
getResources(), R.drawable.ic_launcher);
MultiTouchView mt1 = new MultiTouchView(this, backgroundCard);
linear.addView(mt1);
Bitmap backgroundCard2 = BitmapFactory.decodeResource(
getResources(), R.drawable.icon);
MultiTouchView mt2 = new MultiTouchView(this, backgroundCard2);
linear.addView(mt2);
}
}
If you set a background color to the MultiTouchView views, then you will find that the color of the entire screen is same as the color of the 2nd view which was added.
I specified layout params for the child views and i was able to get the views to draw on screen. the modified code:
public class AndroidTouch extends Activity {
LinearLayout linear;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_c);
linear = (LinearLayout)findViewById(R.id.main);
Bitmap backgroundCard = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
int w = backgroundCard.getWidth();
int h = backgroundCard.getHeight();
LayoutParams params = new LayoutParams(w, h);
MultiTouchView mt1 = new MultiTouchView(getApplicationContext(), backgroundCard);
//mt1.setBackgroundColor(Color.RED);//try uncommenting this wihtout layout params change
linear.addView(mt1, params);
Bitmap backgroundCard2 = BitmapFactory.decodeResource(getResources(), R.drawable.image2);
params = new LayoutParams(backgroundCard2.getWidth(), backgroundCard2.getHeight());
MultiTouchView mt2 = new MultiTouchView(getApplicationContext(), backgroundCard2);
//mt1.setBackgroundColor(Color.BLUE);<-- Entire screen turns blue
linear.addView(mt2, params);
}
}
But i believe you will face another problem after this. From the code it is evident that you are trying to draw the views at the touched positions. I would suggest using one single custom view and adding multiple images to the same view. Only in this case you have to determine which view needs to be drawn in a different co-ordinate and which view remains same.
Hope this helps
Related
I want to place different custom view at a certain position that i set and it will always place on the top-left corners.
I have tried the method using
LayoutParams params = new LayoutParams(v1.getWidth(), v1.getHeight());
params.leftMargin = 100;
params.topMargin = 100;
mView.addView(v1,params);
In this way, the left top corner is disappeared...
Further, can I set a rotation on the inserted custom view as well?
please give me some advice to deal with this question
Here is the detail code,
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw_main);
myDraw = (RelativeLayout) findViewById(R.id.myDraw);
Button btnAddRect = (Button) findViewById(R.id.btnAdd);
btnAddRect.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v1 = vi.inflate(R.layout.drawbox, null);
mfView = (SingleFingerView) v1.findViewById(R.id.draw);
myDraw.addView(v1);
// myDraw.addView(v1, params);
myDraw.invalidate();
}
});
}
CustomView
public class SingleFingerView extends LinearLayout{
public SingleFingerView(Context context) { this(context, null, 0); }
public SingleFingerView(Context context, AttributeSet attrs) { this(context, attrs, 0); }
public SingleFingerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.parseAttr(context, attrs);
View mRoot = View.inflate(context, R.layout.test_image_view, null);
mView = (ImageView) mRoot.findViewById(R.id.view);
mPushView = (ImageView) mRoot.findViewById(R.id.push_view);
mPush1DView = (ImageView) mRoot.findViewById(R.id.push1d_view);
mFirmView = (ImageView) mRoot.findViewById(R.id.firm_view);
mRemoveView = (ImageView) mRoot.findViewById(R.id.remove_view);
addView(mRoot, -1, -1);
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setParamsForView(widthMeasureSpec, heightMeasureSpec);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
}
xml of Main
<RelativeLayout
android:id="#+id/myDraw"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:src="#drawable/bg"
/>
Try this, no need to make things so complicated.
That should add your custom view to your relativeLayout with the width height you want and a left and top margins of 100px.
public void onClick(View v) {
mfView = new SingleFingerView(MainActivity.this);
RelativeLayout.LayoutParams prms = new RelativeLayout.LayoutParams(width,height);
prms.setMargins(100,100,0,0);
myDraw.addView(mfView,prms);
}
Hope this helps.
In a project of mine, I have a custom HorizontalScrollView class that displays a line chart. It gets rid of all of the elements and then it adds a single ImageView as a child element. It works fine the first time, but if I were to change to other fragment and switch back to the fragment containing the line chart, the ImageView is not present, although the object is recreated exactly the same way as the first time. If I inspect it with the DDMS the ImageView is really not in the UI graph. Any ideas why?? I really need some help on that.
That is my code (from which I have omitted some irrelevant parts):
public class LineChartView extends HorizontalScrollView {
// Private Constants ...
// Private Fields...
public LineChartView(Context context) {
super(context);
init();
}
public LineChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public LineChartView(Context context, float[] lineValues) {
super(context);
mLineValues = lineValues;
init();
}
public LineChartView(Context context, AttributeSet attrs, float[] lineValues) {
super(context, attrs);
mLineValues = lineValues;
init();
}
private void init() {
// Setting densityMultiplier
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int pixelDensity = displayMetrics.densityDpi;
mDensityMultiplier = pixelDensity / DisplayMetrics.DENSITY_DEFAULT;
// Initalising Paints...
initChildElements();
}
private void initChildElements() {
removeAllViews();
// Adding the image view to the visual graph
mChartImage = new ImageView(getContext());
ViewGroup.LayoutParams chartLayoutParams = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mChartImage.setLayoutParams(chartLayoutParams);
addViewInLayout(mChartImage, 0, mChartImage.getLayoutParams(), true);
}
public void setLineValuesList(float[] lineValuesList) {
if (lineValuesList == null) {
mLineValues = new float[]{};
} else {
mLineValues = lineValuesList;
}
requestLayout();
invalidate();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mChartImage.setImageDrawable(renderLineChart(h, 1.5f)); // Calculate the bitmap with the same height
super.onSizeChanged(w, h, oldw, oldh);
}
private BitmapDrawable renderLineChart(int height, float scale) {
if (height <= 0 || mLineValues.length == 0)
return null;
// Drawing logic... (not really relevant)
return new BitmapDrawable(getContext().getResources(), resultBitmap);
}
private float calculateWidth(float distanceBetween) {
int strokeCount = mLineValues.length - 1;
return strokeCount * distanceBetween;
}
private float calculateDistanceToNextValue(float scale) {
return BASE_DISTANCE_BETWEEN_POINTS * mDensityMultiplier * scale;
}
}
i had a pageView, i use a code from dave to have some views on the same screen, like gallery widget, but the problem its seems its kind slow, not sure how to modify the ontouch event, what can i do to make fast scrollig i had this PageScroll code
public class PagerContainer extends FrameLayout implements ViewPager.OnPageChangeListener {
private ViewPager mPager;
boolean mNeedsRedraw = false;
public PagerContainer(Context context) {
super(context);
init();
}
public PagerContainer(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PagerContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
//Disable clipping of children so non-selected pages are visible
setClipChildren(false);
//Child clipping doesn't work with hardware acceleration in Android 3.x/4.x
//You need to set this value here if using hardware acceleration in an
// application targeted at these releases.
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
#Override
protected void onFinishInflate() {
try {
mPager = (ViewPager) getChildAt(0);
mPager.setOnPageChangeListener(this);
} catch (Exception e) {
throw new IllegalStateException("The root child of PagerContainer must be a ViewPager");
}
}
public ViewPager getViewPager() {
return mPager;
}
private Point mCenter = new Point();
private Point mInitialTouch = new Point();
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenter.x = w / 2;
mCenter.y = h / 2;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
//We capture any touches not already handled by the ViewPager
// to implement scrolling from a touch outside the pager bounds.
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialTouch.x = (int)ev.getX();
mInitialTouch.y = (int)ev.getY();
default:
ev.offsetLocation(mCenter.x - mInitialTouch.x, mCenter.y - mInitialTouch.y);
break;
}
return mPager.dispatchTouchEvent(ev);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Force the container to redraw on scrolling.
//Without this the outer pages render initially and then stay static
if (mNeedsRedraw) invalidate();
}
#Override
public void onPageSelected(int position) { }
#Override
public void onPageScrollStateChanged(int state) {
mNeedsRedraw = (state != ViewPager.SCROLL_STATE_IDLE);
}
}
and this its the web where i take the code:
PageView code and this is the image of what i get since Gallery its depreacted this should be used, and gallery throws me outofmemory exception because im using images (i tried asyntask and a lot of things) Thanks
I have a custom view and want to add one more custom view on that custom view. This is my custom view class:
public class CustomCircle extends View{
float radius;
Paint paint = new Paint();
String message = "";
public CustomCircle(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth()/2, getHeight()/2,radius, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean isClickInCircle = false;
float x = event.getX();
float y = event.getY();
double check = Math.sqrt((x-getWidth()/2)*(x-getWidth()/2) + (y-getHeight()/2)*(y-getHeight()/2));
if (check<=radius) {
isClickInCircle= true;
}
if (isClickInCircle) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Toast.makeText(getContext(),message, Toast.LENGTH_LONG).show();
return true;
case MotionEvent.ACTION_UP:
Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
return true;
default:
break;
}
}
return false;
}
and am using another class that extends LinearLayout:
public class B extends LinearLayout {
private Paint paint;
public B(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Style.FILL);
}
public void addCircle() {
CustomCircle circleBlue = new CustomCircle(getContext(), null);
circleBlue.paint.setColor(Color.WHITE);
circleBlue.paint.setAntiAlias(true);
circleBlue.radius = 160;
circleBlue.message = "Clicked";
addView(circleBlue);
CustomCircle circleRed = new CustomCircle(getContext(), null);
circleRed.paint.setColor(Color.RED);
circleRed.paint.setAntiAlias(true);
circleRed.radius = 80;
circleRed.message = "Clicked";
addView(circleRed);
}
and I'm calling the B class from the main activity class using :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
B root = new B(this);
root.addCircle();
setContentView(root);
}
The output is showing me only one circle instead of a circle inside another circle. What's wrong with my code?
And the Output is showing me only One circle instead of circle inside
circle.
You picked the wrong layout if you want to overlap children, a RelativeLayout or FrameLayout is the way to go. Also, regarding your code:
public class B extends RelativeLayout {
//...
public void addCircle() {
// the constructor that uses the AttributeSet should be added if you use the
// custom component in the xml layout
CustomCircle circleBlue = new CustomCircle(getContext());
// ...
// add it with LayoutParams
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp.addRule(RelativeLayout.CENTER_IN_PARENT);
addView(circleBlue, rlp);
// the same for the other view
}
Also your two circle will have the same dimensions so they will overlap perfectly(and you'll not be able to see them), you would need to give them different dimensions, through the LayoutParams, for example:
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(200, 200);
for the first one and:
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(100, 100);
for the second one.
Is it possible that there are 2 circles in the layout but you can see only one
because it has the same color as the first circle and they are laying on top of each other?
change circleRed.paint.setColor(Color.WHITE);
to circleRed.paint.setColor(Color.BLACK);
and see what it gives
I have a custom ImageView('CustomImageView') and an Edit-text in a linear layout of an activity 'ImageViewActivity'. The Edit-text is initially set invisible. When the customimageview is touched, and onDraw() is called, I want the visibility of the Edit-text to be set visible. Where should I put the code for this?
Code for ImageViewActivity:
public class ImageViewActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_imageview);
}
}
And the code for CustomImageView is:
public class CustomImageView extends ImageView {
Paint paint = new Paint();
float xp = -1, yp = -1;
private Options opt;
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
xp = event.getX();
yp = event.getY();
invalidate();
}
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//some code
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (xp >= 0 && yp > 0) {
canvas.drawCircle(xp, yp, 20, paint);
}
}
}
Implement touch listener on your customImageview class and then call the edittext to hide it or show is as you need, for results of touch on custom view you have to define touchlistener on your customview not of activity and you can manage views of parent activity in touchevent of customview OR other method is implement touch listener on you activity and find the view which is touched if touched view is your custom view then make visible your Edittext. Then you will not need to do anything in onDraw() as regarding the edittext.
I'd recommend setting the view to visible once you have detected a touch motion on your particular view. Specifically it doesn't matter how the user touches it, since once they touch it you want to show your view (at least that is what you said you wanted).