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.
Related
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.
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);
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.
As showing on the picture. I want to display the star image above layout .
I am new to this type of coding .
my query is
1)will It possible to display star(image) on my layout side?
2)If on every click on my event I want to display star like and display like second image will it possible?
Means on same screen I have to save the star with their respect position .
thanks in Advanced?
Something like this :
public class MyActivity extends Activity implements View.OnTouchListener {
private RelativeLayout _mainLayout;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_mainLayout = (RelativeLayout)findViewById(R.id.canvas);
_mainLayout.setOnTouchListener(this);
}
#Override
public boolean onTouch(View view, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
ImageView image = new ImageView(this);
image.setImageBitmap(bitmap);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(bitmap.getWidth(), bitmap.getHeight());
layoutParams.leftMargin = X - bitmap.getWidth()/2;
layoutParams.topMargin = Y - bitmap.getHeight()/2;
layoutParams.bottomMargin = -250;
layoutParams.rightMargin = -250;
image.setLayoutParams(layoutParams);
_mainLayout.addView(image);
break;
}
return false;
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
android:id="#+id/canvas"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/bg0large"
>
</RelativeLayout>
To do layout over layout, you should to use RelativeLayout.
If you want to display one layout over another layout you should use FrameLayout
http://developer.android.com/resources/articles/layout-tricks-merge.html
I have a RelativeLayout that contains a WebView and a ListView (ListViewContainer is a subclass of ListView:
public AdListViewContainer(Context context, ServiceLookup lookup, MarketList list, Registry registry, BitmapCache bitmapCache, Utilities utilities, ActionFlipper flipper) {
super(context);
mScale = getContext().getResources().getDisplayMetrics().density;
final int orientation = getResources().getConfiguration().orientation;
setClickable(true);
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mAd = new WebView(context);
mAd.setId(1234);
mAd.setWebViewClient(new AdListWebClient());
mAd.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d (TAG, "Inner Event " + event.getAction());
return false;
}
});
mAd.getSettings().setJavaScriptEnabled(true);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
lp.addRule(ALIGN_PARENT_BOTTOM, 1);
addView(mAd, lp);
}
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
if (mAd != null) {
lp.addRule(ALIGN_BOTTOM, mAd.getId());
}
mListContainer = new ListViewContainer(context, lookup, list, registry, bitmapCache, utilities, flipper);
addView(mListContainer, lp);
}
The WebView is showing an ad generated by Adition, basically an img-tag in an a-tag.
The problem I have is that the ad can't be clicked. No touch or click events are received by the WebView. When I remove the ListView and the WebView is the only child of the ViewGroup (by removing the last addView call), the ad is clickable and everything is fine.
ListViewContainer is a straightforward subclass of ListView that contains a load of clickable LinearLayouts.
Any help appreciated!
Ok, I found the issue. The ListView was overlapping the WebView, caused by using ALIGN_BOTTOM instead of ABOVE. D'Oh. HierarchyViewer was a blast in finding this.
I overrode OnTouchEvent for the Webview, and put the WebView inside of a FrameLayout, filling it, then put everything else I needed on top of the webview. Working great!