drag and drop function onTouch event fails - java

Hi I wrote an app using drag'n drop option, Im using android studio 3 & sdk 26
When I get to the touch event I get the error message:
java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
Thats the code:
private View.OnTouchListener OnTouchListener() {
return new View.OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
final int x = (int) motionEvent.getRawX();
final int y = (int) motionEvent.getRawY();
switch (motionEvent.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:
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;
}
};
}
I used that code before and it worked, I cant understand whats wrong here.

Based on the error message the issue has nothing to do with the drag and drop, it looks like this part of code:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams)
view.getLayoutParams();
and
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
.getLayoutParams();
should be changed to :
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams)
view.getLayoutParams();
and
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view
.getLayoutParams();
You didn't put your xml, but I am supposing that parent of "view" is a LinearLayout right?

Related

Set width and height of a lottie animation view programmatically

int width=30;
int height=30;
LottieAnimationView lottieanimation=findViewById(R.id.ltanms);
lottieanimation.setLayoutParams(new RelativeLayout.LayoutParams(width,height));
But this isn't working for me.
You can try this:
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) LottieAnimationView.getLayoutParams();
params.width = width;
params.height = height;
it worked for me.

Setting margin on view in RelativeLayout programmatically doesn't have any affect

In Android, I create an ImageView in the Java code and set its layout parameters: width, height and top margin before adding it to the main layout (RelativeLayout). The width and height are applied successfully, but the margin doesn't have any affect on the image view position. The actual top margin stays 0.
How to apply the top margin to views? The code is below.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initClouds();
}
private void initClouds() {
addCloud(R.drawable.cloud1, R.dimen.cloud1_top_margin);
addCloud(R.drawable.cloud2, R.dimen.cloud2_top_margin);
}
private void addCloud(int imageResId, int topMarginResId) {
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.mainLayout);
ImageView cloud = new ImageView(this);
int height = (int) getResources().getDimension(R.dimen.cloud_height);
int width = (int) getResources().getDimension(R.dimen.cloud_width);
ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(width, height);
params.topMargin = (int) getResources().getDimension(topMarginResId);
cloud.setImageResource(imageResId);
mainLayout.addView(cloud, params);
}
}
For setting the margin for a view inside RelativeLayout you should use RelativeLayout.LayoutParams . Change your code like this ,
private void addCloud(int imageResId, int topMarginResId) {
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.mainLayout);
ImageView cloud = new ImageView(this);
int height = (int) getResources().getDimension(R.dimen.cloud_height);
int width = (int) getResources().getDimension(R.dimen.cloud_width);
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(width, height);
param.topMargin = (int) getResources().getDimension(topMarginResId);
cloud.setImageResource(imageResId);
mainLayout.addView(cloud, param);
}

How to limit view movement in onTouch to a parentview in Android?

This seems to be easy to state but there seems no straight forward implementation. I want to limit the movement of an imageview to its direct parent. I couldn't find examples related to this. Can somebody help me with an example for this?
I actually want to achieve a motion where the leaf in middle is moved, the leaf at the top should move to bottom and the bottom leaf should move to the middle and the middle leaf should move to top position. This coupled with the elevation of the middle leaf. Please refer to the image below.
I have tried to achieve this by using the rect of the parent view in onTouch of the view but that doesn't seem to work. Tried to achieve this listview and recyclerview but that seems to add a lot of complexity to a simple requirement.
Here is my code
public class Main6Activity extends AppCompatActivity {
ImageView imageView;
private int _xDelta;
private int _yDelta;
View view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main6);
imageView = (ImageView)findViewById(R.id.img1);
view = findViewById(R.id.imglayout);
final Rect rect = new Rect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom());
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
if(event.getAction() == MotionEvent.ACTION_DOWN){
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) imageView.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
}
if (event.getAction() == MotionEvent.ACTION_MOVE){
if(isViewContains(X,Y)){
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
imageView.setLayoutParams(layoutParams);
}
}
return true;
}
});
}
private boolean isViewContains(int rx,int ry) {
int[] l = new int[2];
view.getLocationOnScreen(l);
Rect rect1 = new Rect(l[0], l[1], l[0] + view.getWidth(), l[1] + imageView.getHeight());
return rect1.contains(rx, ry);
}
}

Multiple RelativeLayout's all programmatically

Below is what my layout looks like.
What I want is for the 2 green arrows to be centered vertically in the top left square. Also, the double number sign ("##") needs to be centered vertically and horizontally in the top left square.
Then, the other set of double number signs need to be centered vertically and horizontally in the top right square.
Below is the code.
public class Puzzle extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dividers();
topLeft();
topRight();
setContentView(relativelayout);
}
public void topLeft() {
RelativeLayout.LayoutParams params0 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params0.addRule(RelativeLayout.ABOVE, view0.getId());
params0.addRule(RelativeLayout.LEFT_OF, view1.getId());
relativelayout.addView(topLeftRL, params0);
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params1.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params1.addRule(RelativeLayout.CENTER_HORIZONTAL);
topLeftRL.addView(puzzle, params1);
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params2.addRule(RelativeLayout.CENTER_VERTICAL);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
topLeftRL.addView(left, params2);
RelativeLayout.LayoutParams params3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params3.addRule(RelativeLayout.CENTER_VERTICAL);
params3.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
topLeftRL.addView(right, params3);
RelativeLayout.LayoutParams params4 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params4.addRule(RelativeLayout.CENTER_IN_PARENT);
topLeftRL.addView(levelCounter, params4);
left.setImageResource(R.drawable.left_arrow);
right.setImageResource(R.drawable.right_arrow);
puzzle.setText(c.getResources().getString(R.string.puzzlePuzzleTV));
levelCounter.setText("###");
}
public void topRight() {
RelativeLayout.LayoutParams params0 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params0.addRule(RelativeLayout.ABOVE, view0.getId());
params0.addRule(RelativeLayout.RIGHT_OF, view1.getId());
relativelayout.addView(topRightRL, params0);
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params1.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params1.addRule(RelativeLayout.CENTER_HORIZONTAL);
topRightRL.addView(record, params1);
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.addRule(RelativeLayout.CENTER_HORIZONTAL);
topRightRL.addView(moves, params2);
RelativeLayout.LayoutParams params3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params3.addRule(RelativeLayout.CENTER_IN_PARENT);
topRightRL.addView(movesCounter, params3);
movesCounter.setText("##");
record.setText(c.getResources().getString(R.string.puzzleRecordTV) + " " + "##");
moves.setText(c.getResources().getString(R.string.puzzleMovesTV));
}
public void dividers() {
// vertical line (top of screen)
RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(5, height / 6);
params1.addRule(RelativeLayout.CENTER_HORIZONTAL);
params1.setMargins(0, 10, 0, 10); // left, top, right, bottom
relativelayout.addView(view1, params1);
// horizontal line (top of screen)
RelativeLayout.LayoutParams params0 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 5);
params0.addRule(RelativeLayout.BELOW, view1.getId());
params0.setMargins(10, 0, 10, 0); // left, top, right, bottom
relativelayout.addView(view0, params0);
// horizontal line (button of screen)
RelativeLayout.LayoutParams params3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 5);
params3.addRule(RelativeLayout.ABOVE, linearlayout.getId());
relativelayout.addView(view3, params3);
}
}
So it looks like when I add multiple addRule() to a param, it doesn't read both of them. I think the problem lies in this line of the topLeft() method: params0.addRule(RelativeLayout.ABOVE, view0.getId());. I've tried switching this line with the other addRule in that param and the result is the same. Why is this?
EDIT #1
- Cleaned up my code to make neater and easier to read.
You are using params that require an anchor. You need to use "addRule (int verb, int anchor)"
so like
params1.addRule(RelativeLayout.ALIGN_PARENT_TOP,1);
I found the answer to my own question. The error was in a part of my onCreate() method that I had not included in my opening post! This was the problem code:
view0.setId(0);
Apparently the id cannot be set to 0. Anyways, I changed the id number to a positive number and everything worked.

Nothing Showing When Dynamically Creating a Relative Layout

Hi I've been having problems with my code with null pointer exceptions (see my other questions) so I've gone for creating my view dynamically.
Here's my code:
public class HarvestLifeActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//add touch listeners for buttons : assign each a name and link it.
View MoveUp = findViewById(R.id.up);
MoveUp.setOnTouchListener(this); // use (this) to link to the current onTouchListener references in class declaration above.
View MoveDown = findViewById(R.id.down);
MoveDown.setOnTouchListener(this);
View MoveLeft = findViewById(R.id.left);
MoveLeft.setOnTouchListener(this);
View MoveRight = findViewById(R.id.right);
MoveRight.setOnTouchListener(this);
}
#Override
protected void onStart() {
super.onStart();
Drawable standing = getResources().getDrawable(R.drawable.test_circle);
//code to convert character size from pixel to dp
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float logicalDensity = metrics.density;
int pxToConv = 50;
int convToDp = (int) (pxToConv / logicalDensity + 0.5);
RelativeLayout characterContainer = new RelativeLayout(this);
RelativeLayout.LayoutParams characParams = new RelativeLayout.LayoutParams(convToDp, convToDp);
characParams.addRule(RelativeLayout.CENTER_IN_PARENT);
characterContainer.setBackgroundDrawable(standing);
characterContainer.setId(101);
}
// Process button clicks
public boolean onTouch(View v, MotionEvent event) {
switch(v.getId()){
case R.id.up:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//as long as up button is pressed it will keep moving character up
while (event.getAction() == MotionEvent.ACTION_DOWN)
{
RelativeLayout characterContainer = (RelativeLayout) findViewById(101);
Drawable walking = getResources().getDrawable(R.drawable.test_circle_red);
int startX = characterContainer.getLeft();
int startY = characterContainer.getTop();
int defaultWidth = characterContainer.getWidth();
int defaultHeight = characterContainer.getHeight();
//create new position for character 1 pixel closer to the top of screen
int newX = startX - 1;
int newY = startY;
//remove character
RelativeLayout view = (RelativeLayout) characterContainer;
ViewGroup owner = (ViewGroup) view.getParent();
owner.removeView(view);
//re make character in new position created above and assign background as walking forwards animation
RelativeLayout.LayoutParams characParams = new RelativeLayout.LayoutParams(defaultWidth,defaultHeight);
characParams.leftMargin = newY;
characParams.topMargin = newX;
characterContainer.setLayoutParams(characParams);
characterContainer.setBackgroundDrawable(walking);
}
break;
// when button is let go of
case MotionEvent.ACTION_UP:
RelativeLayout characterContainer = (RelativeLayout) findViewById(101);
Drawable standing = getResources().getDrawable(R.drawable.test_circle);
characterContainer.setBackgroundDrawable(standing);
default:
break;
}
return true;
case R.id.down:
.. ..
}
return true;
}
}
When I run it the created layout is not there.
Is there something I've missed?
You are creating a RelativeLayout object, but never setting it as the content for the window...
make your onCreate Look like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Cut these lines out of onStart();
RelativeLayout characterContainer = new RelativeLayout(this);
RelativeLayout.LayoutParams characParams = new RelativeLayout.LayoutParams(convToDp, convToDp);
characParams.addRule(RelativeLayout.CENTER_IN_PARENT);
characterContainer.setBackgroundDrawable(standing);
characterContainer.setId(101);
setContentView(characterContainer);
//add touch listeners for buttons : assign each a name and link it.
/*View MoveUp = findViewById(R.id.up);
MoveUp.setOnTouchListener(this); // use (this) to link to the current onTouchListener references in class declaration above.
View MoveDown = findViewById(R.id.down);
MoveDown.setOnTouchListener(this);
View MoveLeft = findViewById(R.id.left);
MoveLeft.setOnTouchListener(this);
View MoveRight = findViewById(R.id.right);
MoveRight.setOnTouchListener(this);*/
}
you are not adding your created layout to the existing view.
thats your problem.
addview(your_layout);

Categories