I'm a beginner with Android development (and Java). I've a number of ImageView in a layout (2d array of images). What I'm trying to implement is, each time when I click on an ImageView, it should set an image from an array based on some logic with current image being displayed (e.g. next image in array, with each click). I have googled and managed to do this but it looks rather long.
public class GameActivity extends AppCompatActivity {
private int [] inputTiles = {R.drawable.one, R.drawable.two, ...// more images};
Random r = new Random();
int matSize = 5;
int[][] indexMat = new int[matSize][matSize];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
for (int i=0; i<matSize; i++) {
for (int j=0; j<matSize; j++) {
indexMat[i][j] = r.nextInt(10);
}
}
final ImageView tile00 = findViewById(R.id.tile00);
tile00.setImageResource(inputTiles[indexMat[0][0]]);
tile00.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
indexMat[0][0] = (indexMat[0][0]+1)%5;
tile00.setImageResource(inputTiles[indexMat[0][0]]);
}
});
final ImageView tile01 = findViewById(R.id.tile01);
tile01.setImageResource(inputTiles[indexMat[0][1]]);
tile01.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
indexMat[0][1] = (indexMat[0][1]+1)%5;
tile01.setImageResource(inputTiles[indexMat[0][1]]);
}
});
...// a lot more ImageViews
}
}
Say I'm displaying 5x5 grid of images. I've the available images in an array inputTiles and a 5x5 array indexMat to store the index of current image at a location i, j. Then, for each ImageView I'm listening for click and choosing another image to display from array. This is working perfectly, but I have to write "clicklisten and action" block 25 times, in this particular example. It'd be really great if there's a way to loop this so that I can have any n x n grid.
I tried looping after a bit googling, by keeping ImageView in a 5x5 array and looping over it, but the loop variables doesn't seem to go inside the setOnClickListener() function. It says I need to make i and j as final but then it becomes constants, so doesn't work. Below code is what I tried, but it doesn't work that way.
final ImageView[][] tiles = {{findViewById(R.id.tile00), findViewById(R.id.tile01), findViewById(R.id.tile02),...},
{findViewById(R.id.tile10), ...,}};
for (int i=0; i<3;i++){
for (int j=0; j<3; j++){
tiles[i][j].setImageResource(inputTiles[indexMat[i][j]]);
tiles[i][j].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
indexMat[i][j] = //doesn't work
}
});
}
}
Any ideas?
The simplest way of doing this is to have a RecyclerView with a GridLayoutManager. Here's a nice example about how you can achieve your desired functionality in a RecyclerView.
Once you are setting these images in your RecyclerView, you can easily manage the click listener in your onBindViewHolder function, based on the position you have clicked.
Related
i am new to development. i am creating an android calculator app with advanced functionality.The thing is i am using text view for taking and displaying inputs/outputs. My question is, how can i take Multiple inputs in multiple Textviews.
For example i have 3 text views,when user will enter 1st input in first textview(by default) and when user press the specific button it moves automatically to next textview . In some cases i want to take 2 inputs and in some cases i want to take 3 ,
How can i achieve this
Note: I dont want to use edit text , coz all buttons of already available in my app.Using Edit text will make softkeyboard to appear, and then for hiding the softkeyboard, i need to use hiding code lines in every class
You can do something like following:
private TextView[] textViews;
private TextView tvCurrentEditing;
private Button btnNext;
private Button btnPrev;
private Button btnSetText;
private int index = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
textViews = new TextView[3];
//Initialize all your textviews like textViews[0] = findViewById(<textview-id1>);
//textViews[1] = findViewById(<textview-id2>);
//textViews[2] = findViewById(<textview-id3>);
tvCurrentEditing = textViews[index];// I am assuming this is your first
//initialzie btnSettext
btnSettext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tvCurrentEditing.setText("<what ever you want");
}
});
//initialize next buton
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(index < textViews.length) {
index++;
}
tvCurrentEditing = textViews[index];
}
});
//Initialize previous button
btnPrev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(index > 0) {
index--;
}
tvCurrentEditing = textViews[index];
}
});
}
The names of the views could be different. The point is always use tvCurrentEditing whenever you want to change data of TextView. And update tvCurrentEditing whenever needed.
I have several TextView objects that I need to animate with the same Animation.
The way I'm doing it looks wrong, since I can only set Animation to each object at time
#Override
public void onClick(View v) {
Animation hideLeftBar, showLeftBar;
hideLeftBar = new TranslateAnimation(195, 0, 0, 0);
hideLeftBar.setDuration(1000);
hideLeftBar.setFillAfter(true);
showLeftBar = new TranslateAnimation(0, 195, 0, 0);
showLeftBar.setDuration(1000);
showLeftBar.setFillAfter(true);
switch(v.getId())
{
case R.id.btGMG:
if(img_GMG.getAlpha() == (float) 0.3)
{
img_GMG.setAlpha((float) 1);
imgLeftBar.startAnimation(showLeftBar);
txtRS.startAnimation(showLeftBar);
txtST.startAnimation(showLeftBar);
txtTR.startAnimation(showLeftBar);
txtI1.startAnimation(showLeftBar);
txtI2.startAnimation(showLeftBar);
txtI3.startAnimation(showLeftBar);
txtP1.startAnimation(showLeftBar);
txtP2.startAnimation(showLeftBar);
txtP3.startAnimation(showLeftBar);
txtS1.startAnimation(showLeftBar);
txtS2.startAnimation(showLeftBar);
txtS3.startAnimation(showLeftBar);
txtFP1.startAnimation(showLeftBar);
txtFP2.startAnimation(showLeftBar);
txtFP3.startAnimation(showLeftBar);
textIndutive.startAnimation(showLeftBar);
textCapacitive.startAnimation(showLeftBar);
}
else
{
img_GMG.setAlpha((float) 0.3);
imgLeftBar.startAnimation(hideLeftBar);
txtRS.startAnimation(hideLeftBar);
txtST.startAnimation(hideLeftBar);
txtTR.startAnimation(hideLeftBar);
txtI1.startAnimation(hideLeftBar);
txtI2.startAnimation(hideLeftBar);
txtI3.startAnimation(hideLeftBar);
txtP1.startAnimation(hideLeftBar);
txtP2.startAnimation(hideLeftBar);
txtP3.startAnimation(hideLeftBar);
txtS1.startAnimation(hideLeftBar);
txtS2.startAnimation(hideLeftBar);
txtS3.startAnimation(hideLeftBar);
txtFP1.startAnimation(hideLeftBar);
txtFP2.startAnimation(hideLeftBar);
txtFP3.startAnimation(hideLeftBar);
textIndutive.startAnimation(hideLeftBar);
textCapacitive.startAnimation(hideLeftBar);
}
break;
}
}
How can I reduce this? Should I do it programatically or using XML resources?
You should use an AnimatorSet. It has a playTogether() function that will play all your animations at the same time. See a good example here.
In order to run multiple animations in parallel you could use the View's ViewPropertyAnimator like this:
for (int i = 0; i < parentView.getChildCount(); i++) {
View childView = parentView.getChildAt(i);
childView.animate().translationX(DELTA_X).setDuration(DURATION_ANIM);
}
and for the other animation you could use .translationY()
It should implements programmatically. You can do this with ListView if all of your elements show same as each other. With ListView you can do more with your elements so easily.
List View | Android Developers
But if you want change this code rapidly you can use List of TextViews and use it easily:
List<TextView> textViews = null;
public void onCreate(View v) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textViews.add(findViewById(R.id.txtRS));
textViews.add(findViewById(R.id.txtST));
//Initialize other textViews here.
}
public void onClick(View v) {
for (int i = 0; i < textViews.size(); i++) {
textViews.get(i).startAnimation(showLeftBar);
}
}
I have this code :
private ImageView d1;
private ArrayList<Integer> listaImagenes = new ArrayList<Integer>();
private ArrayList<String> listaFrases = new ArrayList<String>();
private Button button;
private Integer contador = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.rellenarImagenes();
setContentView(R.layout.imagentonas);
d1 = (ImageView) findViewById(R.id.imagenes01);
while (contador < listaImagenes.size()) {
d1.setImageResource(listaImagenes.get(contador));
button = (Button) findViewById(R.id.botoncillo);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
contador++;
}
});
}
}
private void rellenarImagenes() {
listaImagenes.add(R.drawable.a01);
listaImagenes.add(R.drawable.a02);
listaImagenes.add(R.drawable.a03)
}
I am trying do a loop that when I press the button , increment contador and d1 change image.
but it is not working, application background remains black and not working.
remove while loop and setimage in onclick method.
You are expecting that modifying the value of the variable contador would result in the array item to change.
Keep in mind that in the code line d1.setImageResource(listaImagenes.get(contador));, the get function receives an int. So at the time where it's called it receives a value, not a reference to an Integer. When you change the value of contador, the value that was used to obtain the index in the array is not changed.
And even if the value did change, d1 would still be using the same resource.
What you need to do in the onClickListener is add the code to set the image. Something along the lines of
public void onClick(View v) {
++contador;
if (contador >= listaImagenes.size())
{
contador=0;
}
//you'll probably need to modify the next line to be able to access the button variable.
//one way to do it is to use a final variable in the onCreate method that creates this OnClickListener
button.setImageResource(listaImagenes.get(contador));
}
The while loop is not needed. What your code is doing is setting the image to the 3 items of the array, one after the other, and adding a new click listener 3 times.
I will try to answer and point some of the flaws you have in the code.
wat if there were 100 drawable like R01 ,R02...? Instead you can use getting drawable using string.
why are you using while loop ? since you have the counter you can directly use that.
Let me try to write the code
int contador=1;
#Override
public void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.imagentonas);
context=this;
d1=(ImageView)findViewById(R.id.imagenes01);
button=(Button)findViewById(R.id.botoncillo);
button=(Button)findViewById(R.id.botoncillo);
button.setOnClickListener( new View . OnClickListener () {
public void onClick ( View v ) {
int id = context.getResources().getIdentifier("a"+contador,
"drawable", context.getPackageName());
d1.setImageResource(id);
contador++;
}
});
}
Notice : int id = context.getResources().getIdentifier("a"+contador,"drawable", context.getPackageName()); Here using the string you can access the drawable this solves the issue for any number of consecutive drawables.
Hope you get the concept...
Thanks
I have this thing into my application.
That I want to do is this, when someone presses the die with the number 5 I want to add 5 points into his ArrayList. I was thinking for an Listener but how would I know which ImageView has been pressed?
Currently I am using this method to get the right placeholders in the board
public ImageView[] initiateDice() {
ImageView pDice1 = (ImageView) findViewById(R.id.die_one);
ImageView pDice2 = (ImageView) findViewById(R.id.die_two);
ImageView pDice3 = (ImageView) findViewById(R.id.die_three);
ImageView pDice4 = (ImageView) findViewById(R.id.die_four);
ImageView pDice5 = (ImageView) findViewById(R.id.die_five);
ImageView pDice6 = (ImageView) findViewById(R.id.die_six);
ImageView pDice7 = (ImageView) findViewById(R.id.die_seven);
ImageView pDice8 = (ImageView) findViewById(R.id.die_eight);
ImageView[] placeHolders = new ImageView[] {pDice1, pDice2, pDice3, pDice4, pDice5, pDice6, pDice7, pDice8};
return placeHolders;
}
and I am "printing" the dice on the screen using that method
public void printDice(int[] array1, ImageView[] array2) {
for (int i = 0; i < array1.length; i++) {
array2[i].setImageResource(diceImages[array1[i] - 1]);
array2[i].setVisibility(View.VISIBLE);
}
}
where the first array is 8 random generated numbers for the dice and the second array is the PlaceHolders.
The diceImages is for the images of the dice, the six states of them.
private final int[] diceImages = new int[] {R.drawable.dice_one, R.drawable.dice_two, R.drawable.dice_three,
R.drawable.dice_four, R.drawable.dice_five, R.drawable.dice_pico };
Any thoughts or suggestions are welcome.
Other answers are providing some of the solution, but you're actually asking about how to get the number displayed in the image view, in which case, you can save it to the tag:
public void printDice(int[] array1, ImageView[] array2) {
for (int i = 0; i < array1.length; i++) {
array2[i].setImageResource(diceImages[array1[i] - 1]);
array2[i].setVisibility(View.VISIBLE);
array2[i].setTag(array1[i]);
}
}
And modifying Matt's answer:
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View v) {
Integer dieValue = v.getTag();
// do something
}
};
pDice1.setOnClickListnener(listener);
pDice2.setOnClickListnener(listener);
pDice3.setOnClickListnener(listener);
pDice4.setOnClickListnener(listener);
pDice5.setOnClickListnener(listener);
pDice6.setOnClickListnener(listener);
pDice6.setOnClickListnener(listener);
pDice8.setOnClickListnener(listener);
One way to do it is to set an OnClickListener like this:
OnClickListener listener = new OnClickListener() {
#Override
public void onClick(View v) {
if (v == pDice1) {
// do something
} else if (v == pDice2) {
...
}
}
};
pDice1.setOnClickListnener(listener);
pDice2.setOnClickListnener(listener);
pDice3.setOnClickListnener(listener);
pDice4.setOnClickListnener(listener);
pDice5.setOnClickListnener(listener);
pDice6.setOnClickListnener(listener);
pDice6.setOnClickListnener(listener);
pDice8.setOnClickListnener(listener);
You would set an OnClickListener() to all ImageViews. The OnClickListener() gets passed the View that has clicked. View has a getId() that returns an int with the id of the View. Then it is only a matter of adding either a switch or if(){...} else if(...)() to perform a specific action based on the id of the View that was clicked.
Look at following android code. IMGS is a 2 dimensional array of ImageView. I am adding onClickListener to it in a for loop. How to identify which view has been clicked ? I dont want to iterate over all the 36 elements using view.getId();.
private static final Integer[] Icons = {
R.drawable.r,
R.drawable.re,
R.drawable.u,
R.drawable.et,
R.drawable.w,
R.drawable.ya
};
private ImageView[][] IMGS= new ImageView[6][6];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IMGS[0][0] = (ImageView) findViewById(R.id.immg11);
for (int i=0; i < 6; i++)
{
for (int j=0; j<6; j++)
{
Drawable d = getResources().getDrawable(Icons[i]);
IMGS[i][j].setImageDrawable(d);
IMGS[i][j].setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//HOW TO KNOW WHICH VIEW HAS BEEN CLICKED ?
}
});
}
}
}
Notice the View argument passed to onClick(View v)? It's the view that was clicked.
You can call v.getId() to retrieve its id.
Agreed, but there are 36 elements over which i have to iterate if I use this method. Is there a way to know the indexes of clicked IMGS ?
You can use setTag() to save whatever data you want in each view and retrieve it later with getTag().