I am using the following code to display images from drawable folder.
But now i want to display pictures dynamically.Every time a new image is added to the drawable folder i don't want go again in the code and add it in the array it should automatically increment and get displayed.
Any Idea how should I go about this.Just started working on Android.
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Menu;
import android.widget.ImageView;
import android.app.Service;
import android.os.Handler;
public class MainActivity extends AppCompatActivity {
private static ImageView imgView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgView = (ImageView) findViewById(R.id.imageView);
final int[] images=images{R.drawable.ic_launcher,
R.drawable.ic_launcher1,R.drawable.ic_launcher2,etc..};
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
int i=0;
public void run() {
imgView.setImageResource(images[i]);
i++;
if(i>images.length-1)
{
i=0;
}
handler.postDelayed(this,5000); //for interval...
}
};
handler.postDelayed(runnable, 5000); //for initial delay..
}
if you want to add the image Dynamically you can Naming the image File like this : Image1.png; Image2.png; and so on.
And then you dont need to call all of them in the array, instead you can using lopp to get the name of the image in resource.
and then get the id using the code below :
public int getID(String resourceName,Context context){
Resources resources = context.getResources();
final int resourceId = resources.getIdentifier(resourceName, "drawable",
context.getPackageName());
return resourceId;
}
Note : after adding the image don't forget to increament the loop. hope it helps.
please keep variable i as static
i.e static int i=0;
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
imgView.setImageResource(images[i]);
i++;
if(i>images.length-1)
{
i=0;
}
handler.postDelayed(this,5000); //for interval...
}
};
handler.postDelayed(runnable, 5000); //for initial delay..
change the handle code as follow
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
imgView.setImageResource(images[i]);
if(i>images.length-1)
{
i=0;
}
else
{
i++;
}
handler.postDelayed(this,5000); //for interval...
}
};
handler.postDelayed(runnable, 5000); //for initial delay..
Related
I'm attempting to make my textView invisible for 4 seconds and then appear after using the code:
final TextView textView233 = findViewById(R.id.textView233);
textView233.setText("Loading data...");
textView233.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
textView233.setVisibility(View.INVISIBLE);
}
}, 4000);
In the situation where I have over 100 textViews in my activity and I want ALL textviews to do the same, is there a way to apply it to all textViews other than writing the code for all 100 of them? Any help would be appreciated, thanks!
add all these TextView inside some LinearLayout and hide the LinearLayout layout after the given internal instead of hiding each and every TextView separately.
You can do it with a custom class:
AnimTextView.java
import android.os.Handler;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Arrays;
public class AnimTextView {
private ArrayList<TextView> textViewList;
public AnimTextView(TextView ... textViews) {
textViewList = new ArrayList<>();
textViewList.addAll(Arrays.asList(textViews));
}
public void startLoading(){
for (final TextView textView: textViewList) {
textView.setText("Loading data...");
textView.setVisibility(View.VISIBLE);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
textView.setVisibility(View.INVISIBLE);
}
}, 4000);
}
}
}
Now, In your Main Activity:
AnimTextView animTextView = new AnimTextView(textView1, textView2, textView3, textView4, ...);
And when you need to start loading:
animTextView.startLoading();
Here is function that will get all TextViews of the Activity(even nested) and hide, you can call it from your Handler:
fun recursiveHideTextAllViews(parent: ViewGroup?) {
for (i in 0 until parent!!.childCount) {
val child: View? = parent.getChildAt(i)
if (child is ViewGroup) {
recursiveHideTextAllViews(child as ViewGroup?)
} else if (child!!.javaClass == AppCompatTextView::class.java) {
child.visibility = View.INVISIBLE;
}
}
}
parent is your Root view
I am new to making android apps, and I don't know how to run a piece of code multiple times.
Here is my code:
package com.example.test;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import java.util.Random;
import android.widget.AbsoluteLayout;
import android.util.*;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
int score = 0;
TextView scoreText;
ImageButton mole;
Random random = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scoreText = findViewById(R.id.scoreCount);
mole = findViewById(R.id.mole);
//I want to run this multiple times
TimeUnit.MILLISECONDS.sleep(random.nextInt(500));
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams) mole.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width);
absParams.y = r.nextInt(height);
mole.setLayoutParams(absParams);
}
#Override
public void onClick(View v) {
}
}
I am trying to make a mole game where the mole randomly goes across the screen and you have to tap it to earn points, the thing is though, I don't know how to run
TimeUnit.MILLISECONDS.sleep(random.nextInt(500));
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams) mole.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width);
absParams.y = r.nextInt(height);
mole.setLayoutParams(absParams);
again and again. I've tried doing
Thread test = new Thread(new Runnable() {
#Override
public void run() {
try {
//I want to run this multiple times
TimeUnit.MILLISECONDS.sleep(500);
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams) mole.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width);
absParams.y = r.nextInt(height);
mole.setLayoutParams(absParams);
}catch(InterruptedException e){
Log.i("Error", "Thread");
}
}
});
test.start();
But it keeps returning the following error:
com.example.test E/AndroidRuntime: FATAL EXCEPTION: Thread-1057
Process: com.example.test, PID: 25335
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7266)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1065)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.requestLayout(View.java:19098)
at android.view.View.setLayoutParams(View.java:12590)
at com.example.test.MainActivity$1.run(MainActivity.java:48)
at java.lang.Thread.run(Thread.java:818)
you can use RxJava as #Mohammad Reza Khahani mentioned which make life easier but if you don't want to get in to it you have two option to run your Thread and change the UI.
first one is to create Handler and inside of your Thread use it to run your code related to UI:
Handler handler = new Handler(); // create new instance in ui thread eg: #onCreate or #onResume
handler.post(new Runnable() {
#Override
public void run() {
//UI changes
}
});
Or you can use YourActivity.this.runOnUiThread method of activity inside of your background-thread to run your UI related code.
runOnUiThread(new Runnable() {
#Override
public void run() {
//UI changes
}
});
I have built a fortune cook app that previously currently has values hardcoded into an array
FortuneActivity.java
package juangallardo.emofortunecookie;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.Random;
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox = new FortuneBox();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
FortuneBox.java
package juangallardo.emofortunecookie;
import java.util.Random;
public class FortuneBox {
public String[] mFortunes = {
"What is the point?",
"Sometimes it is best to just sleep in.",
#98 other fortunes...
};
// Methods (abilities)
public String getFortune() {
String fortune = "";
// Randomly select a fortune
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFortunes.length);
fortune = mFortunes[randomNumber];
return fortune;
}
}
The problem is that now I want to add a Spanish version. So I realize that i should add that array into the strings.xml.
I looked up string resources on the Android developer page. and it gave me the idea to add this to my code
strings.xml
<string-array name="emo_fortunes">
<item>What is the point?</item>
<item>Sometimes it is best to just sleep in.</item>
</string-array>
But now I am stuck on where to add this part that has the part about Resources, etc.
I followed along to a tutorial from Treehouse about strings but my app kept crashing.
Basically the change that I made was to make the original array into
FortuneBox.java
# above unchanged from previous code
public String[] mFortunes;
# below unchanged from previous code
FortuneActivity.java
# same imports as before
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox = new FortuneBox();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
Resources resources = getResources();
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
These were my errors, but not sure where to go from here as I am new to Android and I have not touched Java since college.
log
FortuneActivity.java
FortuneBox.java
Mikki has the right answer, but it is a little confusing. In your code above, you are using the same name for two different variables: mFortuneBox. This is the root of your trouble:
private FortuneBox mFortuneBox = new FortuneBox();
...
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
Change the second one to a different name, like this, and the errors go away:
final String[] fortunes = resources.getStringArray(R.array.emo_fortunes);
However, you still aren't using these fortunes from the array anywhere. You can actually delete fortunes from your Activity and move it to your FortuneBox class instead. This is slightly tricky, though, as you need to know what the context is to get a string array resource in your other class. The context is the Activity, so you need to pass this along as a parameter when you create your FortuneBox object.
I'd recommend a slight restructuring. Below are the two files that should work for you:
FortuneActivity.java
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
mFortuneBox = new FortuneBox(this);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
FortuneBox.java
public class FortuneBox {
public String[] mFortunes;
public FortuneBox(Context context) {
Resources resources = context.getResources();
mFortunes = resources.getStringArray(R.array.emo_fortunes);
}
// Methods (abilities)
public String getFortune() {
String fortune = "";
// Randomly select a fortune
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFortunes.length);
fortune = mFortunes[randomNumber];
return fortune;
}
}
Your problem is simple. You can not access a non-final from an inner class (in this case your OnClickListener).
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
Try just changing the line to look like this one above.
Hope it helps.
The mFortuneBox variable in the previous way you have used is an object of FortuneBox class and hence this call mFortuneBox.getFortune() works.
In the later changed code, you have made mFortuneBox variable a reference to an Array of strings. But still tried calling mFortuneBox.getFortune(). 'getFortune()' is a method of FortuneBox class right, so you can call it with an object of Forune Box class itself.
Try doing this:
final String[] fortuneArray = resources.getStringArray(R.array.emo_fortunes);
and
private FortuneBox mFortuneBox = new FortuneBox();
Now call mFortuneBox.getFortune(fortunearray) sending it this array to the getfortune method.
Now let the getFortune() method randomly pick one from this array passed and return the random string picked
I have following code which is as a final result giving me list of images from Android device larger than 500 KB:
package com.click;
import java.io.File;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.widget.LinearLayout;
import android.widget.TextView;
public class SkanerActivity extends Activity {
private File root;
private ArrayList<File> fileList = new ArrayList<File>();
private LinearLayout view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_skaner);
//TEST
view = (LinearLayout) findViewById(R.id.view);
//getting SDcard root path
root = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath());
getfile(root);
for (int i = 0; i < fileList.size(); i++) {
TextView textView = new TextView(this);
textView.setText(fileList.get(i).getName());
textView.setPadding(5, 5, 5, 5);
System.out.println(fileList.get(i).getName());
if (fileList.get(i).isDirectory()) {
textView.setTextColor(Color.parseColor("#FF0000"));
}
view.addView(textView);
}
}
public ArrayList<File> getfile(File dir) {
File listFile[] = dir.listFiles();
if (listFile != null && listFile.length > 0) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
// Zakomentowane aby nie dodawac do listy folderów
// fileList.add(listFile[i]);
getfile(listFile[i]);
} else if (listFile[i].length() >= 500 * 1024) {
if (listFile[i].getName().endsWith(".png")
|| listFile[i].getName().endsWith(".jpg")
|| listFile[i].getName().endsWith(".jpeg")
|| listFile[i].getName().endsWith(".gif"))
{
fileList.add(listFile[i]);
}
}
}
}
return fileList;
}
}
Now I would like to create new class to process further with new operations on this list of images - in new class.
My question is: how can I handle and declare fileList as a variable (Object) to be used in other class (new Java class)? I know, that in Java there isn't such method as "Global variable", but for sure is there any method to use result of script in other place (Class) in Application.
Can you please help me with my issue? Many thanks in advance for your help!
If by new class you mean new Activity then you can pass data using
Intent intent = new Intent(getBaseContext(), NewClass.class);
intent.putExtra("imageList", fileList);
startActivity(intent);
But prior to that you need to get reference to this List in the current class
fileList = getfile(root);
But if you simply mean need a new Class for processing. Simply create a new class. Define a constructor/method that takes ArrayList<File> argument. Create an object of this new class from your current class passing the list of files as argument and call the method in it for your further processing logic.
class ImagesProcessorClass {
List<File> imageList;
public ImagesProcessorClass (List<file> imageList) {
this.imageList = imageList;
}
public void processsImages(){
//do processing on imageList
}
}
and in your present class do
public class SkanerActivity extends Activity {{
//your present code
protected void onCreate(Bundle savedInstanceState) {
//your present code
fileList = getfile(root);
ImagesProcessorClass imageProcessor = new ImagesProcessorClass (fileList);
imageProcessor.processsImages();
}
}
If you want to use it in another activity, you can use something like that
Intent intent = new Intent(this, AnotherActivity.class);
intent.putExtra("List", fileList);
startActivity(intent);
And in AnotherActivity have to do this
Intent data = getIntent();
List<File> files = (List<File>)data.getSerializableExtra("List");
Also you can make this list static and create method to get it;
Make fileList a private member of the class. Then add accessor methods to access it from outside the class . You will of course need to create an object of SkanerActivity to do so.
class SkanerActivity{
...
private ArrayList<File> fileList = new ArrayList<File>();
public getFileList(){
return fileList;
}
...
}
Class Access{
void function1(){
SkanerActivity obj = new SkanerActivity();
List fileList = obj.getFileList();
..
}
I am trying with no success to modify the code example from:
http://www.inter-fuser.com/2009/08/android-animations-3d-flip.html
so it will rotate the images in a loop, when clicking on the image once. (second click should pause).
I tried using Handler and threading but cannot update the view since only the main thread can update UI.
Exception I get from the code below:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
[in 'image1.startAnimation(rotation);' ('applyRotation(0, 90);' from the main thread)]
package com.example.flip3d;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
public class Flip3d extends Activity {
private ImageView image1;
private ImageView image2;
private boolean isFirstImage = true;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
image1 = (ImageView) findViewById(R.id.image01);
image2 = (ImageView) findViewById(R.id.image02);
image2.setVisibility(View.GONE);
image1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (isFirstImage) {
applyRotation(0, 90);
isFirstImage = !isFirstImage;
} else {
applyRotation(0, -90);
isFirstImage = !isFirstImage;
}
}
});
}
private void applyRotation(float start, float end) {
// Find the center of image
final float centerX = image1.getWidth() / 2.0f;
final float centerY = image1.getHeight() / 2.0f;
// Create a new 3D rotation with the supplied parameter
// The animation listener is used to trigger the next animation
final Flip3dAnimation rotation =
new Flip3dAnimation(start, end, centerX, centerY);
rotation.setDuration(500);
rotation.setFillAfter(true);
rotation.setInterpolator(new AccelerateInterpolator());
rotation.setAnimationListener(new DisplayNextView(isFirstImage, image1, image2));
if (isFirstImage)
{
image1.startAnimation(rotation);
} else {
image2.startAnimation(rotation);
}
}
}
How can I manage to update the UI and control the rotation within onClick listener?
Thank you,
Oakist
Try wrapping the UI code in runOnUIThread()