I'm stuck on this problem in Android Drag and Drop. I've already read the documentation and more than one question/answer here on stackoverflow .
The problem is that:
i've 3 ImageView that can i move inside another 3 ImageView, but when i start to drag one of the 3 ImageView i can drop it inside in just one ImageView area.
Here the code! . Basically i'll see active only the dropViewArancio area even if i drag the other ImageView.
What i want it's to have all the 3 area active where i can drop one of the 3 ImageView.
Thanks for the support!
An ImageView can't contain another View inside, only classes derived from ViewGroup can. Then you can move an ImageView over or behind another (depending on Z order) but not inside.
Here a working example of how to move all the views contained in a RelativeLayout using onTouch. I think that onDrag event applies better to drag and drop data items, not to move views. Hope it will help
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
private RelativeLayout mRelLay;
private float mInitialX, mInitialY;
private int mInitialLeft, mInitialTop;
private View mMovingView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRelLay = (RelativeLayout) findViewById(R.id.relativeLayout);
for (int i = 0; i < mRelLay.getChildCount(); i++)
mRelLay.getChildAt(i).setOnTouchListener(this);
}
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
RelativeLayout.LayoutParams mLayoutParams;
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
mMovingView = view;
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mInitialX = motionEvent.getRawX();
mInitialY = motionEvent.getRawY();
mInitialLeft = mLayoutParams.leftMargin;
mInitialTop = mLayoutParams.topMargin;
break;
case MotionEvent.ACTION_MOVE:
if (mMovingView != null) {
mLayoutParams = (RelativeLayout.LayoutParams) mMovingView.getLayoutParams();
mLayoutParams.leftMargin = (int) (mInitialLeft + motionEvent.getRawX() - mInitialX);
mLayoutParams.topMargin = (int) (mInitialTop + motionEvent.getRawY() - mInitialY);
mMovingView.setLayoutParams(mLayoutParams);
}
break;
case MotionEvent.ACTION_UP:
mMovingView = null;
break;
}
return true;
}
}
So, i've solved my problem following this tutorial. Anyway my desire solution it's something similar this, the perfect way it's a mixing of tutorial and a previous link. Thanks all for help.
Related
I'm trying to create a custom view with the height bigger than the display's (or parent's) height. This view must be scrollable. I use onTouchEvent to measure new finger position, and I actually get what I want, but my view doesn't move. I've searched in the internet for the problem's solution, but didn't find a suitable answer.
This's my View
public class SmartScroll extends View{
public SmartScroll(Context context) {
super(context);
}
int count = 0;
int yStart = 0, yEnd = 0;
#Override
public boolean onTouchEvent(MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
yStart = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
MeasureSpec.toString(getMeasuredHeight());
MeasureSpec.toString(getMeasuredWidth());
count++;
yEnd = (int) event.getY();
scrollBy(0, (yEnd - yStart));
yStart = yEnd;
break;
case MotionEvent.ACTION_UP:
yStart = 0;
yEnd = 0;
break;
}
return true;
}
and this's how I create it inActivity:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SmartScroll scrollView = new SmartScroll(getApplicationContext()) {
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(1500, MeasureSpec.EXACTLY));
}
};
scrollView.setBackgroundDrawable(getResources().getDrawable(R.drawable.gradient));
setContentView(scrollView);
}
}
Please, help me to make it work
Unfortunately I didn't find the answer on my question. I tried some working examples from the internet which use scrollBy() or scrollTo() and they really work.
So, I found solution that works for me. As I couldn't move the content of my custom view, I decided to move the whole view.
I do this by listening to onTouchEvents, and setting new Y coordinates of my view. After setting new Y I call invalidate().
UPDATE:
I finally found the reason of my initial problem. It was in the way I created my custom ViewGroup. I set height of my ViewGroup bigger than the height of its parent and wanted to scroll its content. But content was the same size of the very ViewGroup, so scrollBy() didn't find the need to scroll content.
What I did was I filled my ViewGroup with children so that the content became bigger than the view, measured my ViewGroup to MatchParent and scrollBy() finally started working.
I am currently working on an application which should be able to detect which individual textviews in a gridlayout are touched. Goal is to set the background color of the touched views to a different color. I am creating the views like this:
for (int row = 1; row < 13; row++) {
for (int col=0; col<24; col++) {
TextView tv = new TextView(this);
GridLayout.LayoutParams params = new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(col));
params.width = (int)(screenWidth / 24);
params.height = (int) (tenth_heigth * 8) / 12 ;
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER);
tv.setBackgroundColor(Color.WHITE);
tv.setText("A");
tv.setTextAppearance(this, android.R.style.TextAppearance_Large);
gridLayout.addView(tv, params);
}
}
I tried to do this with an overridden onTouchEvent method within the activity, but so far I had no luck achieving my goal. What's the best way to do this?
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
// would like to set the background color of the touched view to blue
break;
case MotionEvent.ACTION_MOVE :
// would like to set the background color of the touched views to red
break;
case MotionEvent.ACTION_UP :
// set the background color to purple
break;
}
return super.onTouchEvent(event);
}
I would appreciate if someone could point me in the right direction. Thanks a lot!
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
int x = (int) event.getX() ;
int y = (int) event.getY();
System.out.println("xxx");
release=(ImageView)findViewById(R.id.imageView2);
RelativeLayout.LayoutParams lp =new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); //Assuming you use a RelativeLayout
ImageView iv=new ImageView(getApplicationContext());
System.out.println("YYYY");
lp.setMargins(x,y,0,0);
System.out.println("aaaa");
iv.setLayoutParams(lp);
System.out.println("bbbbb");
iv.setImageDrawable(getResources().getDrawable(R.drawable.pain_icon));
System.out.println("ccccc");
((ViewGroup)v).addView(release);
}
return true;
}
You haven't added the dynamicallly created view to ur parent. first declare ur parent and add this iv (imageview in ur code) to the parent using relativeLayout.addView(iv);
i'm guessing here since you din't post the error.
R.id.imageView2 most likely has a parent and you are trying to add it to another viewgroup. thats whats causing the error. you need to create a new instance of ImageView then add it to your view group
ImageView im = new ImageView(this);
im.setImageResource(R.drawable.nameofimage);
((ViewGroup)v).addView(im);
I've been struggling on the last couple of days with this program. The issue that I'm facing is about a drop event of a view which excludes another view. What the program is supposed to do is, on a click of a button, creates as many ImageButtons and they all can be dragged and dropped anywhere on the screen. However, he creates the first view and creates the second, but when I drag the second ImageButton, the first one created is deleted from the screen.
Here is the XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/relative_main"
tools:context=".WhyItActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="add button"
android:onClick="addButton" />
</RelativeLayout>
Below is the java activity responsible
public class WhyItActivity extends Activity {
private RelativeLayout relative;
private LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_why_it);
params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
relative = (RelativeLayout)findViewById(R.id.relative_main);
// all the screen be a dropping area
relative.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View view, DragEvent event) {
View dragView = (View) event.getLocalState();
RelativeLayout layout = (RelativeLayout) view;
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
break;
case DragEvent.ACTION_DRAG_ENTERED:
break;
case DragEvent.ACTION_DRAG_EXITED:
break;
case DragEvent.ACTION_DROP:
int right = (int)event.getX();
int top = (int)event.getY();
params.setMargins(right, top, 0, 0);
layout.removeView(dragView);
layout.addView(dragView, params);
// set back the visibility
dragView.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
break;
default:
break;
}
return true;
}
});
}
/** OnClick */
public void addButton(View v){
// params for centralizing the image button
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
// new object
ImageButton imgBtn = new ImageButton(this);
imgBtn.setImageDrawable(getResources().getDrawable(R.drawable.ic_launcher));
relative.addView(imgBtn, params);
// letting the view be dragged around the screen
imgBtn.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder builder = new View.DragShadowBuilder(view);
view.startDrag(data, builder, view, 0);
// let the view be invisible while dragging the object
view.setVisibility(View.INVISIBLE);
return true;
}
});
}
So, the question is... Where I'm screwing? I create a new object, if it's was a matter of just one view on the screen it would be working just fine.
Thanks for reading so far, and possibly be able to help.
One silly but critical mistake.
Add this line
params = params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
Above
params.setMargins(right, top, 0, 0);
As u can see there is only one instance of LayoutParam you have been assigning to all your views, thus ending up in stack of views.
Please mark as accepted if resolved. Thanks.
For an app I need to develop, I need to be able to select one view from ViewGroup when user long press on the view have to popup an alert dialog, from that i will select options depending on the requirement, those are delete view and change background color for that particular view. I am creating different custom view's ( Custom view extends from View) and It has Touchlistener's. Dynamically attaching those view's to layout (RelativeLayout). Let us assume my layout having 3 views.
My questions:
I want to select one view from the list of available view's on the layout.
How to restrict the Custom view size instead of occupying full parent view.
I am facing Problem's like this: Look at this image if i set background color for custom view it look like this, Actually i was set for layout background color White here custom view occupies full screen. so, unable to see parent background color. Here problem with customview size, unable to restrict the customview size rather than occupying full parent view. even if i touch outside of my custom view, the touch listeners of custom view was triggering. i want to restrict those touch listeners upto my customview only..
.
Main Requirement:
Finally i want to be achieve like this below image, Now i am able to add more custom view's to layout,but unable to delete selected one. When i long press on any one of the view from the layout, it should popup one alert dialog with two buttons, if i select one selected view should be delete for another selection background color change.
RelaventCode: i am adding view to layout like this.
findViewById(R.id.line).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CustomView drawView = new CustomView(context);
frame.addView(drawView);
}
});
and this is the customview :
public class CustomView extends View {
public CustomView (Context context) {
super(context);
init();
}
private void init() {
Paint paint = new Paint();
Paint pai = new Paint();
Path path = new Path();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
path.lineTo(50, 100);
}
#Override
public void onDraw(Canvas canvas) {
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(Top_Point.x, Top_Point.y);
path.lineTo(Right_Point.x, Right_Point.y);
path.lineTo(Left_Point.x, Left_Point.y);
path.lineTo(Top_Point.x, Top_Point.y);
path.close();
canvas.drawPath(path, Inner_Paint);
canvas.drawLine(Top_Point.x, Top_Point.y, Right_Point.x, Right_Point.y,
Lines_Paint);
canvas.drawLine(Right_Point.x, Right_Point.y, Left_Point.x,
Left_Point.y, Lines_Paint);
canvas.drawLine(Left_Point.x, Left_Point.y, Top_Point.x, Top_Point.y,
Lines_Paint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
PointF NewP = new PointF(0, 0);
NewP.x = event.getX();
NewP.y = event.getY();
if (TopTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_TOP;
} else if (RightTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_RIGHT;
} else if (LeftTouchArea.contains(event.getX(), event.getY())) {
currentTouch = TOUCH_LEFT;
} else if (a) {
Translate_Point.x = event.getX();
Translate_Point.y = event.getY();
currentTouch = Inner_Touch;
return true; // Return false if user touches none of the
// corners
} else {
return false;
}
return true;
case MotionEvent.ACTION_MOVE:
switch (currentTouch) {
case TOUCH_TOP:
/* ------ */
case TOUCH_RIGHT:
/* ----- */
invalidate();
return true;
case TOUCH_LEFT:
/* ------ */
invalidate();
return true;
case Inner_Touch:
/* ------ */
invalidate();
return true;
}
return false;
case MotionEvent.ACTION_UP:
switch (currentTouch) {
case TOUCH_TOP:
/* ----- */
return true;
case TOUCH_RIGHT:
/* ----- */
return true;
case TOUCH_LEFT:
/* ----- */
return true;
case Inner_Touch:
/* ----- */
invalidate();
return true;
}
return false;
}
return super.onTouchEvent(event);
}
You should override onSizeChanged or onMeasure methods to let your ViewGroup know your view's size. And make sure that your view's width and height are both WRAP_CONTENT.
About touch event - problem here is that your view size is matching parent size, so it intercepts all touch events (since it returns true in onTouchEvent).
And here is a great tutorial
Add an OnLongClickListener to the customview before adding it to the view group.
To help identify the view at a higher level, you may want to set an identifier on the view using setTag("id", id);
If I understand you correctly, the view you add is too big and fills it's parent.
Isn't it sufficient to do something like
TwoPointsDraw drawView = new TwoPointsDraw(context);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
drawView.setLayoutParams(lp)
frame.addView(drawView);
Checkout this project, it might be helpful => Android multitouch controller, a simple multitouch pinch zoom library for Android.
Here is another example.