Reputation: 692
I have just learnt how to create cardview dynamically. I'm using a button press to create a cardview and i have set onTouchListener to it. When i'm creating only one card onTouchListener is working perfectly but as soon as I'm creating one more card onTouchListener isn't working as expected. When I have 2 cards and I try to move 1st card it's moving 2nd one instead of 1st.
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
Context context;
ImageView imageView;
RelativeLayout relativeLayout;
static int pos=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
context=this;
relativeLayout=(RelativeLayout)findViewById(R.id.rl_layout);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
CreateCardViewWithoutImageView();
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
return true;
}
public void CreateCardViewWithoutImageView(){
final CardView cardview=new CardView(context);
cardview.setId(++pos);
cardview.setLayoutParams((new CardView.LayoutParams(600, 600)));
cardview.setContentPadding(25,25,25,25);
cardview.setCardBackgroundColor(Color.MAGENTA);
relativeLayout.addView(cardview);
}
private final View.OnTouchListener mListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View card, MotionEvent event) {
// The View (v) here is a CardView as the onTouchListener is set to it
RelativeLayout.LayoutParams layoutParamsRL = (RelativeLayout.LayoutParams) ((CardView) card).getLayoutParams();
float dx = 0, dy = 0, x = 0, y = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
card.bringToFront();
dx = event.getRawX() - layoutParamsRL.leftMargin;
dy = event.getRawY() - layoutParamsRL.topMargin;
}
break;
case MotionEvent.ACTION_MOVE: {
x = event.getRawX();
y = event.getRawY();
layoutParamsRL.leftMargin = (int) (x - dx);
layoutParamsRL.topMargin = (int) (y - dy);
card.setLayoutParams(layoutParamsRL);
}
break;
case MotionEvent.ACTION_UP: {
}
break;
}
return true;
}
};
}
Upvotes: 0
Views: 246
Reputation: 3869
It's because your cardview
variable is global. So each time you create a new CardView it's replaced so the listener is always using the last CardView created.
You should do something like:
// Note: By the way, you should NOT use a capital letter to name a function
public void createCardViewWithoutImageView(){
//CardView
final CardView cardview = new CardView(context);
//....
}
You are going to have the same issue with layoutParamsRL
as it should be local too.
// Context context; // You don't need to store the context here as you are in the activity
// CardView cardview; // Don't need to be global
// RelativeLayout.LayoutParams layoutParamsRL; // Don't need to be global
ImageView imageView;
RelativeLayout relativeLayout;
static int pos = 0; // Are you sure it needs to be a static field?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// context=this;
relativeLayout = (RelativeLayout) findViewById(R.id.rl_layout);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
createCardViewWithoutImageView();
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
return true;
}
public void createCardViewWithoutImageView() {
//CardView
CardView cardview = new CardView(MainActivity.this);
cardview.setId(++pos);
cardview.setLayoutParams((new CardView.LayoutParams(600, 600)));
cardview.setContentPadding(25, 25, 25, 25);
cardview.setCardBackgroundColor(Color.MAGENTA);
cardview.setOnTouchListener(mListener);
relativeLayout.addView(cardview);
}
private final View.OnTouchListener mListener = new View.OnTouchListener() {
float dx, dy; // Moved outside the onTouch method in order to them to keep their value.
@Override
public boolean onTouch(View card, MotionEvent event) {
Log.d("OnTouchListener", "don't touch me :p");
// The View (v) here is a CardView as the onTouchListener is set to it
RelativeLayout.LayoutParams layoutParamsRL = (RelativeLayout.LayoutParams) ((CardView) card).getLayoutParams();
float x = 0, y = 0;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
card.bringToFront();
dx = event.getRawX() - layoutParamsRL.leftMargin;
dy = event.getRawY() - layoutParamsRL.topMargin;
}
break;
case MotionEvent.ACTION_MOVE: {
x = event.getRawX();
y = event.getRawY();
layoutParamsRL.leftMargin = (int) (x - dx);
layoutParamsRL.topMargin = (int) (y - dy);
card.setLayoutParams(layoutParamsRL);
}
break;
case MotionEvent.ACTION_UP: {
}
break;
}
return true;
}
};
Upvotes: 1
Reputation: 116
//Create the Global object to make use of it in assign new property as u want
CardView selectedCardview;
@Override
protected void onCreate(Bundle savedInstanceState) { //....... }
//will create inner object
public void CreateCardViewWithoutImageView(){
CardView cardview = new CardView(context);
//Setting the default property u want:)
cardview.setId(++pos);
cardview.setLayoutParams((new CardView.LayoutParams(600, 600)));
.......
final CardView tempCardView=cardview;
cardview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN :
{
selectedCardview=tempCardView;
.........and adding action as u want
}
........... add another cases
}
}
...........
}
now selectedCardview u use will represent the cardview u touch it and will be easy to set its property as it global
void setProperty(){
/******** add what u want here********/
selectedCardview.setBackgroundColor(Color.RED);
}
Upvotes: 0
Reputation: 116
1- the variable is global so u need to defined in inside method as mention above 2- you can easily change its properties with another method and pass it the cardview object as parameter 3- you can keep the global object to represent the selected cardview as in touchevent method will assign the cardview that fire event to the global and do what u want with it
Upvotes: 0