I decided to try to created custom view. It is necessary to create editor with some capabilities(rotate, zoom, transform, adding overlays) on both layers(top, bottom) and make it possible to move devider to increase one layout for convenient image editing. Are there any similar works or may be someone have imagine how to start right?
I've made a custom layout that does what you asked for.
Use it programmatically, like in the example
git repository here
public class BicontLayout extends LinearLayout {
private View divider;
private View vTop, vBottom;
private LinearLayout.LayoutParams vTopParams, vBottomParams;
private int dividerClickableHeight;
public BicontLayout(Context ctx, View viewTop, View viewBottom) {
super(ctx);
this.vTop = viewTop;
this.vBottom = viewBottom;
setOrientation(LinearLayout.VERTICAL);
setWeightSum(1f);
vTopParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.5f);
vBottomParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 0.5f);
addView(vTop, vTopParams);
divider = new View(ctx);
divider.setBackgroundColor(Color.RED);
dividerClickableHeight = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50f, getResources().getDisplayMetrics());
addView(divider, LinearLayout.LayoutParams.MATCH_PARENT, 3);
addView(vBottom, vBottomParams);
}
private float yStartTouch;
private float yStartWeight;
private boolean isDragging;
private int[] dividerLocation = new int[2];
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(onTouchEvent(ev)) return true;
return super.onInterceptTouchEvent(ev);
}
#Override
public boolean onTouchEvent(MotionEvent me) {
switch(me.getAction()) {
case MotionEvent.ACTION_DOWN:
yStartTouch = me.getRawY();
yStartWeight = vTopParams.weight;
divider.getLocationOnScreen(dividerLocation);
isDragging = Math.abs(dividerLocation[1]-yStartTouch) < dividerClickableHeight/2;
break;
case MotionEvent.ACTION_MOVE:
if(!isDragging) break;
float yDelta = me.getRawY() - yStartTouch;
float yDeltaProg = yDelta/BicontLayout.this.getHeight();
float yNewProg = yStartWeight + yDeltaProg;
if(yNewProg<0.1f) yNewProg=0.1f;
if(yNewProg>0.9f) yNewProg=0.9f;
vTopParams.weight = yNewProg;
vTop.setLayoutParams(vTopParams);
vBottomParams.weight = 1f - yNewProg;
vBottom.setLayoutParams(vBottomParams);
break;
case MotionEvent.ACTION_UP:
isDragging=false;
break;
}
if(isDragging) return true;
return super.onTouchEvent(me);
}
} // author Tiziano Munegato
Usage example
// vTop : top view
// vBottom : bottom view
BicontLayout doubleLayout = new BicontLayout(getContext(), vTop, vBottom);
setContentView(doubleLayout);
Happy coding!
Related
I am working on a project where I have a view, which, once clicked, instantiates a class, passing the view to the constructor, which creates 4 anchor points on to the view. This is done using the following:
customView = new CustomView(MainActivity.this, viewCounter,
customView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Resizer resizer = new Resizer(MainActivity.this, MainActivity.this, container, customView, lblStatus);
}
});
The resizer class is as follows:
public Resizer(Context context, AppCompatActivity activity, ViewGroup container, ViewGroup viewToBeResized, TextView lblStatus)
{
this.context = context;
this.activity = activity;
this.container = container;
this.viewToBeResized = viewToBeResized;
this.lblStatus = lblStatus;
createAnchorPoints();
}
private void createAnchorPoints()
{
Drawable circle = ContextCompat.getDrawable(context, R.drawable.anchor);
int circleSize = dpToPx(CIRCLE_SIZE_DP);
Anchor topLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_LEFT, lblStatus);
topLeftAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams topLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
topLeftParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
viewToBeResized.addView(topLeftAnchor, topLeftParms);
Anchor topRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.TOP_RIGHT, lblStatus);
topRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams topRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
topRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
topRightParms.addRule(RelativeLayout.ALIGN_PARENT_TOP, viewToBeResized.getId());
viewToBeResized.addView(topRightAnchor, topRightParms);
Anchor bottomLeftAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
bottomLeftAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomLeftParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_START, viewToBeResized.getId());
bottomLeftParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomLeftAnchor, bottomLeftParms);
Anchor bottomRightAnchor = new Anchor(context, viewToBeResized, Anchor.ResizeMode.BOTTOM_RIGHT, lblStatus);
bottomRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomRightParms = new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomRightAnchor, bottomRightParms);
}
In the anchor class that gets created at each corner, a touch listener is used. What I am trying to do is as the user drags the anchor view, the main view, that is passed into the anchor, will resize in the direction the user dragged.
Below is my touch listener
public class AnchorTouchListener implements View.OnTouchListener
{
private int _xDelta;
private int _yDelta;
private View viewToResize;
private TextView lblStatus;
private Anchor.ResizeMode resizeMode;
public AnchorTouchListener(View viewToResize, TextView lblStatus, Anchor.ResizeMode resizeMode)
{
this.viewToResize = viewToResize;
this.lblStatus = lblStatus;
this.resizeMode = resizeMode;
}
#Override
public boolean onTouch(View view, MotionEvent event)
{
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
Log.d("Anchor", "Updating X & Y");
int diff = 0;
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
lblStatus.setText("Moving down");
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
lblStatus.setText("Drag finished");
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
lblStatus.setText("Moving around");
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = _xDelta - X;
layoutParams.bottomMargin = _yDelta - Y;
view.setLayoutParams(layoutParams);
//viewToResize.animate().scaleX(0.6f);
if (resizeMode == Anchor.ResizeMode.BOTTOM_RIGHT)
{
diff = diff - X - _xDelta;
Log.d("Anchor Touch", "Diff: " + diff);
if (diff > 0)
{
((RelativeLayout.LayoutParams) viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width + Math.abs(diff);
}
else
{
((RelativeLayout.LayoutParams)viewToResize.getLayoutParams()).width = viewToResize.getLayoutParams().width - Math.abs(diff);
}
}
break;
}
return true;
}
}
It is kind of working, except its not moving smoothly with the anchor, the view being resized seems to grow quicker than what is being dragged and is very erratic at how it resize and shrinks.
Is there a better way for doing what I am trying to achieve or can anyone see what I might be doing wrong.
UPDATE
Added video to show what I am trying to achieve and what the problem is.
Since the anchors are positioned with a RelativeLayout, there is no need to write code to move the anchors. Simply resize the grey box and the anchors will be positioned correctly upon layout. The size of the grey box can be determined by capturing initial conditions of the pointer placement and the initial size of the box to achieve the following.
I have only implemented the bottom right anchor and I have taken some liberties with your implementation, but the concept is still valid for your code and the other anchor points.
AnchorTouchListener.java
public class AnchorTouchListener implements View.OnTouchListener {
private int _xDelta;
private int _yDelta;
private View viewToResize;
private TextView lblStatus;
// private Anchor.ResizeMode resizeMode;
public AnchorTouchListener(View viewToResize, TextView lblStatus/*, Anchor.ResizeMode resizeMode*/) {
this.viewToResize = viewToResize;
this.lblStatus = lblStatus;
// this.resizeMode = resizeMode;
}
private int initialHeight;
private int initialWidth;
private int initialX;
private int initialY;
#Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
Log.d("Anchor", "Updating X & Y");
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
lblStatus.setText("Action down");
// Capture initial conditions of the view to resize.
initialHeight = viewToResize.getHeight();
initialWidth = viewToResize.getWidth();
// Capture initial touch point.
initialX = X;
initialY = Y;
break;
case MotionEvent.ACTION_UP:
lblStatus.setText("Drag finished");
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
lblStatus.setText("Moving around");
RelativeLayout.LayoutParams lp =
(RelativeLayout.LayoutParams) viewToResize.getLayoutParams();
// Compute how far we have moved in the X/Y directions.
_xDelta = X - initialX;
_yDelta = Y - initialY;
// Adjust the size of the targeted view. Note that we don't have to position
// the resize handle since it will be positioned correctly due to the layout.
lp.width = initialWidth + _xDelta;
lp.height = initialHeight + _yDelta;
viewToResize.setLayoutParams(lp);
break;
}
return true;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Drawable circle = ContextCompat.getDrawable(this, R.drawable.circle);
ImageView imageView = new ImageView(this);
imageView.setImageDrawable(circle);
int circleSize = dpToPx(CIRCLE_SIZE_DP);
RelativeLayout viewToBeResized = findViewById(R.id.customView);
ImageView bottomRightAnchor = new ImageView(this);
bottomRightAnchor.setImageDrawable(circle);
RelativeLayout.LayoutParams bottomRightParms =
new RelativeLayout.LayoutParams(circleSize, circleSize);
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_END, viewToBeResized.getId());
bottomRightParms.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, viewToBeResized.getId());
viewToBeResized.addView(bottomRightAnchor, bottomRightParms);
bottomRightAnchor.setOnTouchListener(
new AnchorTouchListener(viewToBeResized, ((TextView) findViewById(R.id.status))));
}
private int dpToPx(int dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
private static final int CIRCLE_SIZE_DP = 20;
}
activity_main.xml
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/customView"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#android:color/holo_green_light" />
<TextView
android:id="#+id/status"
android:layout_width="wrap_content"
tools:text="Status"
android:layout_height="wrap_content" />
</RelativeLayout>
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
In above line of code in your AnchorTouchListener class you are getting the params of the view endpoint you created earlier.
Getting the correct LayourParams should solve the problem.
I'm new to building apps on Android. I do have Java and android studio working experience, and build basic android apps but the project I'm working on now is a little bit complicated.
I want to move a image inside a imageview corresponding to touch pointer, in other words to direction of touch but inside a specific area(circular).
Just like in android app pou i.e. pou eyes move corresponding to touch pointer.
I started with below code:
public class TouchActivity extends Activity {
private ViewGroup mainLayout;
private ImageView image;
private int xDelta;
private int yDelta;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_touch);
mainLayout = (RelativeLayout) findViewById(R.id.main);
image = (ImageView) findViewById(R.id.image);
image.setOnTouchListener(onTouchListener());
}
private OnTouchListener onTouchListener() {
return new OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View view, MotionEvent event) {
final int x = (int) event.getRawX();
final int y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams)
view.getLayoutParams();
xDelta = x - lParams.leftMargin;
yDelta = y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
Toast.makeText(TouchActivity.this,
"thanks for new location!", Toast.LENGTH_SHORT)
.show();
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
layoutParams.leftMargin = x - xDelta;
layoutParams.topMargin = y - yDelta;
layoutParams.rightMargin = 0;
layoutParams.bottomMargin = 0;
view.setLayoutParams(layoutParams);
break;
}
mainLayout.invalidate();
return true;
}
};
}
}
... and successfully managed to move an image corresponding to touch pointer but I want to implement something like this:
(eyes are moving according to touch but inside a specific area)
Any ideas?
(by kalu) Move click image inside imageview ajust height or with depends the size of resource(image) and translate x or y direction.
Try This:
// your image view
ImageView mCoverView = findViewById(R.id.imageview);
Glide.with(aActivity).load(cover) //set img url
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(new BitmapImageViewTarget(mCoverView) {
#Override
protected void setResource(Bitmap resource) {
final Bitmap f_res = resource;
// just if you want change for a drawable res
// final Bitmap f_res = BitmapFactory.decodeResource(aActivity.getResources(),R.drawable.ic_ampliada);
//k ajust center but ajust height or with depend the image
mCoverView.setScaleType(ImageView.ScaleType.CENTER_CROP);
mCoverView.setImageBitmap(f_res);
final String dir;
if(f_res.getWidth()>f_res.getHeight())
dir="x";
else
dir="y";
mCoverView.setOnClickListener(new View.OnClickListener() {
// size of move
int value = 25;
double resh=f_res.getHeight();
double resw=f_res.getWidth();
double coverh =mCoverView.getHeight();
double coverw = mCoverView.getWidth();
int xTranslate = 0;
double sacale_w_from_h = coverh / resh * resw;
//k wtotal distancia do centro as bordas (x=0 (centro imagem))
double wtotal = (sacale_w_from_h/2);
int yTranslate = 0;
double sacale_h_from_w = coverw / resw * resh;
//k wtotal distancia do centro as bordas (y=0 (centro imagem))
double htotal = sacale_h_from_w / 2;
#Override
public void onClick(View v) {
if (dir == "x"){
if (xTranslate>wtotal || xTranslate<-wtotal)
value=-value;
xTranslate += value;
}else if(dir == "y"){
if (yTranslate>htotal || yTranslate<-htotal)
value=-value;
yTranslate += value;
}
this.translateImage(xTranslate,yTranslate);
}
private void translateImage(int xTranslate, int yTranslate)
{
Bitmap translateBitmap = Bitmap.createBitmap(f_res.getWidth() + xTranslate, f_res.getHeight() + yTranslate, f_res.getConfig());
Canvas translateCanvas = new Canvas(translateBitmap);
Matrix translateMatrix = new Matrix();
translateMatrix.setTranslate(xTranslate, yTranslate);
Paint paint = new Paint();
translateCanvas.drawBitmap(f_res, translateMatrix, paint);
mCoverView.setImageBitmap(translateBitmap);
}
});
}
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
if (glideAnimation == null || !glideAnimation.animate(resource, this)) {
setResource(resource);
}
}
});
//-------------------------------------------------------------------
I am developing one app where I am dragging around my ImageView in Activity.
I have configured Facebook Rebound library for spring animation which is originally used in Facebook Messenger's chat heads animations. I want to add this kind of animations to my ImageView when I drag it.
VIDEO
So far I am able to get spring animation when I touch ImageView (implemented spring on rootview), this is my code. How can I implement that natural type of dragging effect to my ImageView.
public class MainTry extends Activity {
int windowwidth;
int windowheight;
private LayoutParams layoutParams;
private final BaseSpringSystem mSpringSystem = SpringSystem.create();
private FrameLayout mRootView;
private Spring spring;
private View mImageView;
private VelocityTracker velocity = null;
private float dx;
private float dy;
private View rootView;
private ImageView img;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
// Create a system to run the physics loop for a set of springs.
SpringSystem springSystem = SpringSystem.create();
// Add a spring to the system.
spring = springSystem.createSpring();
rootView = getWindow().getDecorView()
.findViewById(android.R.id.content);
windowwidth = getWindowManager().getDefaultDisplay().getWidth();
windowheight = getWindowManager().getDefaultDisplay().getHeight();
img = (ImageView) findViewById(R.id.imageView2);
rootView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// spring.setEndValue(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// spring.setEndValue(0);
break;
}
return true;
}
});
// Add a listener to observe the motion of the spring.
spring.addListener(new SimpleSpringListener() {
#Override
public void onSpringUpdate(Spring spring) {
// You can observe the updates in the spring
// state by asking its current value in onSpringUpdate.
float value = (float) spring.getCurrentValue();
float scale = .5f - (value * 0.1f);
img.setScaleX(scale);
img.setScaleY(scale);
}
});
// spring.setEndValue(1);
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
LayoutParams layoutParams = (LayoutParams) img
.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dx = event.getRawX() - 10;
dy = event.getRawY() - 10;
if (velocity == null) {
// Retrieve a new VelocityTracker object to watch the
// velocity of a motion.
velocity = VelocityTracker.obtain();
} else {
// Reset the velocity tracker back to its initial state.
velocity.clear();
}
break;
case MotionEvent.ACTION_MOVE:
dx = event.getRawX() - 10;
dy = event.getRawY() - 10;
velocity.addMovement(event);
spring.setVelocity(velocity.getYVelocity());
spring.setCurrentValue(dy);
spring.setEndValue(dy);
layoutParams.leftMargin = (int) dx - 10;
layoutParams.topMargin = (int) dy - 10;
img.setLayoutParams(layoutParams);
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
velocity.addMovement(event);
spring.setVelocity(velocity.getYVelocity());
spring.setCurrentValue(event.getRawY() - 10);
spring.setEndValue(0);
break;
default:
break;
}
return true;
}
});
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
}
what about this:
class V extends View implements SpringListener {
private static final int NUM_ELEMS = 4;
private Spring[] mXSprings = new Spring[NUM_ELEMS];
private Spring[] mYSprings = new Spring[NUM_ELEMS];
private Paint mPaint = new Paint();
private Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
public V(Context context) {
super(context);
SpringSystem ss = SpringSystem.create();
Spring s;
for (int i = 0; i < NUM_ELEMS; i++) {
s = ss.createSpring();
s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, true));
s.addListener(this);
mXSprings[i] = s;
s = ss.createSpring();
s.setSpringConfig(new MySpringConfig(200, i == 0? 8 : 15 + i * 2, i, false));
s.addListener(this);
mYSprings[i] = s;
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mXSprings[0].setCurrentValue(w / 2);
mYSprings[0].setCurrentValue(0);
mXSprings[0].setEndValue(w / 2);
mYSprings[0].setEndValue(h / 2);
}
#Override
public void onSpringActivate(Spring s) {
}
#Override
public void onSpringAtRest(Spring s) {
}
#Override
public void onSpringEndStateChange(Spring s) {
}
#Override
public void onSpringUpdate(Spring s) {
MySpringConfig cfg = (MySpringConfig) s.getSpringConfig();
if (cfg.index < NUM_ELEMS - 1) {
Spring[] springs = cfg.horizontal? mXSprings : mYSprings;
springs[cfg.index + 1].setEndValue(s.getCurrentValue());
}
if (cfg.index == 0) {
invalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mXSprings[0].setEndValue(event.getX());
mYSprings[0].setEndValue(event.getY());
return true;
}
#Override
protected void onDraw(Canvas canvas) {
for (int i = NUM_ELEMS - 1; i >= 0; i--) {
mPaint.setAlpha(i == 0? 255 : 192 - i * 128 / NUM_ELEMS);
canvas.drawBitmap(mBitmap,
(float) mXSprings[i].getCurrentValue() - mBitmap.getWidth() / 2,
(float) mYSprings[i].getCurrentValue() - mBitmap.getHeight() / 2,
mPaint);
}
}
class MySpringConfig extends SpringConfig {
int index;
boolean horizontal;
public MySpringConfig(double tension, double friction, int index, boolean horizontal) {
super(tension, friction);
this.index = index;
this.horizontal = horizontal;
}
}
}
i have used above V class directly in Window-manager and it's work perfectly and chatHead move like facebook messenger.
public class ChatHeadService extends Service
{
private LayoutInflater inflater;
private WindowManager windowManager;
private Point szWindow = new Point();
#Override
public void onCreate()
{
super.onCreate();
Log.v(Utils.LogTag, "Start Service");
}
private
void handleStart(){
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
if (Build . VERSION . SDK_INT >= Build . VERSION_CODES . HONEYCOMB) {
windowManager . getDefaultDisplay() . getSize(szWindow);
} else {
int w = windowManager . getDefaultDisplay() . getWidth();
int h = windowManager . getDefaultDisplay() . getHeight();
szWindow . set(w, h);
}
WindowManager . LayoutParams params = new WindowManager . LayoutParams(
WindowManager . LayoutParams . WRAP_CONTENT,
WindowManager . LayoutParams . WRAP_CONTENT,
WindowManager . LayoutParams . TYPE_PHONE,
WindowManager . LayoutParams . FLAG_NOT_FOCUSABLE |
WindowManager . LayoutParams . FLAG_WATCH_OUTSIDE_TOUCH |
WindowManager . LayoutParams . FLAG_LAYOUT_NO_LIMITS,
PixelFormat . TRANSLUCENT
);
params . gravity = Gravity . TOP | Gravity . LEFT;
params . x = 50;
params . y = 100;
V vImg = new V(this);
windowManager . addView(vImg, params);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
if (startId == Service . START_STICKY) {
handleStart();
}
}
return super . onStartCommand(intent, flags, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy(){
super . onDestroy();
if (windowManager != null) {
// windowManager.removeView(chatHeadView);
}
}
}
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 want to drag a view. Until now i tried it with a LinearLayout and margins and with a AbsoluteLayout.
AbsoluteLayout example:
button.Touch = (clickedView, motionEvent) =>
{
Button b = (Button)clickedView;
if (motionEvent.Action == MotionEventActions.Move)
{
AbsoluteLayout.LayoutParams layoutParams = new AbsoluteLayout.LayoutParams(100, 35, (int)motionEvent.GetX(), (int)motionEvent.GetY());
b.LayoutParameters = layoutParams;
}
return true;
};
In every case I tried I got a curios behaviour. Here's why. The view i'm dragging follows my finger but jumps always between two positions. One postition hits my finger the other is somewhere to my fingers left-top. If I'm just writing my current position into a textview (without moving the view) the coordinates behave as expected. But if i'm also moving the view they are jumping again.
How can i avoid this?
EDIT: I used sounds comment on my question to implement a working draging for monodroid (it is done for Java/Android SDK in the linked site). Maybe others are interested in doing that some day, so here's my solution:
[Activity(Label = "Draging", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity1 : Activity
{
private View selectedItem = null;
private int offset_x = 0;
private int offset_y = 0;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
ViewGroup vg = (ViewGroup)FindViewById(Resource.Id.vg);
vg.Touch = (element, motionEvent) =>
{
switch (motionEvent.Action)
{
case MotionEventActions.Move:
int x = (int)motionEvent.GetX() - offset_x;
int y = (int)motionEvent.GetY() - offset_y;
int w = WindowManager.DefaultDisplay.Width - 100;
int h = WindowManager.DefaultDisplay.Height - 100;
if (x > w)
x = w;
if (y > h)
y = h;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
LinearLayout.LayoutParams.WrapContent,
LinearLayout.LayoutParams.WrapContent));
lp.SetMargins(x, y, 0, 0);
selectedItem.LayoutParameters = lp;
break;
default:
break;
}
return true;
};
ImageView img = FindViewById<ImageView>(Resource.Id.img);
img.Touch = (element, motionEvent) =>
{
switch (motionEvent.Action)
{
case MotionEventActions.Down:
offset_x = (int)motionEvent.GetX();
offset_y = (int)motionEvent.GetY();
selectedItem = element;
break;
default:
break;
}
return false;
};
}
}