I'm trying to make a simple slideshow that fades out and fades in a few images without a button click. I had found a few examples to assist me, but I am having trouble getting the first image to fade into the second image. As of now, it just fades out and that is it. I have my code below.
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="5000"
android:repeatCount="infinite"
/>
</set>
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="5000"
android:repeatCount="infinite"
/>
</set>
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:inAnimation="#anim/fade_in"
android:outAnimation="#anim/fade_out" >
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="#drawable/image1" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="#drawable/image2" />
</ViewSwitcher>
MainClass.Activity
public class MainClass extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.next);
slideshow();
}
public void slideshow() {
ViewSwitcher switching = (ViewSwitcher)findViewById(R.id.switcher);
if (switching.getDisplayedChild() == 0) {
switching.showNext();
} else {
switching.showPrevious();
}
}
}
In that case, you need to use a timer. You use it like so:
public class MainClass extends Activity {
private Timer timer;
private ViewSwitcher switching;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.next);
switching = (ViewSwitcher)findViewById(R.id.switcher);
timer = new Timer();
timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);
//5000 is in milliseconds, meaning 5 seconds
}
public void slideshow() {
if (switching.getDisplayedChild() == 0) {
switching.showNext();
} else {
switching.showPrevious();
}
}
private class NextImageTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
slideshow();
}
});
}
}
}
What does this chunk of code do? Well, let's go at it step by step. First declare the views
private Timer timer;
private ViewSwitcher switching;
And then initialize them in the onCreate method
switching = (ViewSwitcher)findViewById(R.id.switcher);
timer = new Timer();
Then we start the timer! To start a timer and tell it what to do, we do it like so
timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);
This line of code basically means Hey timer, schedule a task at a fixed rate of 5 seconds. Start immediately!
The first argument is the task to be scheduled, an object, the NextImageTask(). This object contains a Runnable that contains the code to run every interval. The interval is a fixed rate of 5 seconds. In the code however it is written as 5000. This is because the method accepts the third argument as millisecond. To get 5 seconds, we must multiply 5 by 1,000 which results to, yep you guessed it right, 5,000. The timer is asked to start immediately by passing a second argument as 0. This is the delay. If you pass 2000 there, the timer will start after a 2 second delay. Just like the third argument, the method accepts this second argument as millisecond.
Next is the method slideshow() which is the same as the OP. This is what the OP wants to do.
Lastly is the private object, NextImageTask().
private class NextImageTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
slideshow();
}
});
}
}
This is the task that will be done by the timer at the fixed rate/every 5 seconds. It should extend TimerTask for the timer to work properly. TimerTask is an abstract class so the NextImageTask() should implement one method, the run() method. This method should contain the code that the timer will run at a fixed interval. This runs on a different thread so if you need to do something in the UI just like the OP's case, we need to run on the UI thread. This is the reason why we called runOnUiThread here. Finally, inside is another runnable calling the OP's method slideshow().
Related
I am trying to build a music player.
I did everything what is required and the working is smooth but however i can't seem to see my MediaController Controls.
Declaration:private MusicController musicController;
public class MusicController extends MediaController {
public MusicController(Context context) {
super(context);
}
#Override
public void hide() {
}
}
MainActivity.java
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
mainactivity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:background="#FF330000"
android:layout_height="match_parent"
android:id="#+id/recycler_parent_view"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I have added a screenshot.
What could be the problem here?
MainActivity.java
MusicService.java
MusicController.java
MyAdaptor.java
I have included every file that might be important. Please help me look out the problem. Thank You.
I see musicController.show(0); being called only after some click events.
Should you call it also soon after having set the anchorView?
From documentation
void show (int timeout)
Show the controller on screen. It will go away automatically after 'timeout' milliseconds of inactivity.
Try just musicController.show();
EDIT
I saw you overrode the MusicController.hide() method so it shouldn't be removed after the timeout period, but still it seems to me you don't show it when you set the anchorView
UPDATE
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
musicController.show();
}
}, 5000);
I ran your code and I was able to show the controller after applying a delay. Maybe you should show it after your service is connected...not sure about this, but at least you could try this code and then improve it.
I am very new to Android SDK so that question may be very simple.
I try to make am app that shows the current time. I know how to get the current time but i somehow need to update the time. So i try putting a while/if statement that updates the time outside onCreate() and inside main Activity class but 4 errors pop up saying "unexpected end of Decleration.
I cant really find a way to solve this so any help would be much appreciated.
I get the idea that a longer example will be more useful for you.
Make a layout for the application, call the file activity_main.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.timedemo.MainActivity">
<TextView
android:id="#+id/textClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/textView" />
</LinearLayout>
Make a file called MainActivity.java, make it extends Activity (or something else that extends Activity)
Init your layout in the onCreate method.
Use a handler to run code at a delayed time, instead of halting the thread.
public class MainActivity extends AppCompatActivity {
//Handler can be used to send Runnables (code to run) to a specific Thread.
//In this case the UI-thread.
Handler handler = new Handler();
//TextView variable defined in Class-scope.
TextView myTextClock;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Load the layout from activity_main.xml into this Activity.
setContentView(R.layout.activity_main);
//Find the textclock that is mentioned in the activity_main.xml
//Use the ID to find the right View.
//As you can see in the xml-file, the id is 'textClock'.
//Looks like this in the XML --> <TextView android:id="#+id/textClock" />
myTextClock = (TextView) this.findViewById(R.id.textClock);
//Tell the Handler to execute this code at an interval.
handler.postDelayed(codeToRun, 1000);
}
//The runnable contains the code that will be run every second.
Runnable codeToRun = new Runnable() {
#Override
public void run() {
updateTime();
}
};
public void updateTime(){
//Code to update the Clock on the UI-thread
//see: http://developer.android.com/reference/java/text/SimpleDateFormat.html
DateFormat sdf = DateFormat.getDateTimeInstance();
myTextClock.setText(sdf.format(new Date()));
//Make sure it runs the next time too.
handler.postDelayed(codeToRun, 1000);
}
}
Hope this helps you get on the right path.
I'd suggest you use ScheduledThreadPoolExecutor class instead of a while loop. There is an example in this tutorial on how to create a clock app. It can be useful as a starting point.
class ClockTask implements Runnable {
#Override
public void run() {
updateClock();
}
}
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
se.scheduleAtFixedRate(new ClockTask(), 0, 1000, TimeUnit.MICROSECONDS);
I'm not sure how you plan to make this, but keep in mind that you do not stall the Main Thread. So avoid a construction like this:
while(true){ Thread.sleep(1000); updateTime(); }
A better approach would to use Handler, for example:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
updateTime();
}
}, 1000);
http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20long)
Hope this helps ;-)
I am writing a splash screen in android 2.1. I want 20 png images to be shown in an order at the splash screen. I tried to use animation-list but couldn't manage to do it.
Here is my code. Now, there is an image called firstLoadingImage.png. Only that is shown for 5000ms. Then the myappactivity starts. However, I couldn't manage to update the image source during this waiting time. How do you think I can do this?
SplashScreenActivity
package myapp.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
public class SplashScreenActivity extends Activity {
protected boolean _active = true;
protected int _splashTime = 5000; // time to display the splash screen in ms
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
Thread splashTread = new Thread() {
#Override
public void run() {
try {
int waited = 0;
while(_active && (waited < _splashTime)) {
sleep(100);
if(_active) {
waited += 100;
}
}
} catch(InterruptedException e) {
// do nothing
} finally {
finish();
startActivity(new Intent(SplashScreenActivity.this, MyAppActivity.class));
stop();
}
}
};
splashTread.start();
}
}
splashscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/linearLayout"
android:background="#drawable/loading_screen_background" >
<ImageView
android:id="#+id/firstLoadingImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/loading100" />
</LinearLayout>
Frame animations can be achieved by setting it to an AnimationDrawable to the background of an ImageView.
Example:
final AnimationDrawable anim = new AnimationDrawable();
anim.addFrame(Context.getResources().getDrawable(R.drawable.resource_id_of_frame1, durationInMs);
anim.addFrame(Context.getResources().getDrawable(R.drawable.resource_id_of_frame2, durationInMs);
anim.addFrame(Context.getResources().getDrawable(R.drawable.resource_id_of_frame3, durationInMs);
...
anim.addFrame(Context.getResources().getDrawable(R.drawable.resource_id_of_framen, durationInMs);
anim.setOneShot(false);
ImageView myImageView = getImageViewToSet();
myImageView.setBackgroundDrawable(anim);
myImageView.post(new Runnable(){
public void run(){
anim.start();
}
}
So make your splash screen a simple layout with an ImageView or create one and add it to the layout. Set the AnimationDrawable to it and run.
My guess would be to use the function runOnUiThread() after calling sleep in your splash thread. Make a runnable class to change the ImageView background, and run in this function perhaps?
Activity.runOnUiThread()
You could find the tutorial for it
here
In my main activity I have a button with the text "Play". I want the text to gradually grow and then gradually diminish in size. This should loop until the button is clicked. This effect should appear like a gentle glow.
So, I have tried using a Thread to accomplish this:
// Play Button Animation Thread
Thread playAnimation = new Thread() {
public void run() {
try {
int textSize = 25;
while (textSize <= 50) {
playBtn.setTextSize(textSize);
textSize += .10;
sleep(100);
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
finally {
}
}
};
Then, I called the thread with:
playAnimation.start();
It isn't working as I have it, but now I'm thinking there is probably a better way. Any help is appreciated.
There are a couple things wrong with the code you have written:
You have declared your textSize variable as an int. Thus, your attempt to increment the value by 0.1 each iteration is futile because the value is cast back to an int after each operation, dropping off the value you just added (i.e. 25 += 0.1 -> 25.1, cast back to an int -> 25...lather, rinse repeat). So the value you are passing to setTextSize() never actually changes.
Your code does not repeat. That loop will only run once until the value reaches 50, and then stop. You won't get the back/forth effect you are going for.
Your updates to the UI should ALWAYS occur on the main/rendering thread. You should never call any update methods (like setTextSize()) from any thread you have created. This can be solved by employing a Handler to manage the threading for you.
If you want the entire button to animate, you can look at the animation framework like others have suggested. However, to automate just the text size, you are on the right path...we just need to tweak your code based on the points I mentioned above:
Handler mHandler = new Handler();
boolean mReverse = false;
Runnable mUpdate = new Runnable() {
#Override
public void run() {
float current = playBtn.getTextSize();
if(mReverse) {
current -= 0.1;
playBtn.setTextSize(current);
mReverse = (current <= 25);
} else {
current += 0.1;
playBtn.setTextSize(current);
mReverse = (current >= 50);
}
mHandler.postDelayed(mUpdate, 100);
}
}
The Handler is created on the main thread, and all code inside the Runnable is executed on the main thread...so you may update the UI there. postDelayed() takes care of the wait delays so you don't really need to create another thread at all. To start your animation, just call
mHandler.postDelayed(mUpdate, 100);
anywhere in your code. To stop the animation at any time, simply stop calling postDelayed after each iteration.
HTH!
You can use Animation resources to perform the above task.
You need to create an animation resource file (anim_play.xml) and put it in res/anim folder.
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="infinite"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="1.2"
android:toYScale="1.2" >
</scale>
Set the animation to the particular view.
play_btn = (Button) findViewById(R.id.btn_play);
playAnim = AnimationUtils.loadAnimation(this, R.anim.anim_play);
play_btn.startAnimation(playAnim);
remove the animation when the user clicked the button.
play_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
play_btn.clearAnimation();
}
});
Look for animations in android - it is best way to create simple effects.
About you code - changing of user interface are allowed only from main thread, so you can't create another thread for animation.
I wrote a splash screen. But the problem is as the splash screen shown in the screen a keyboard also invoked. What could be the possible reason for this??
Please find the image below
and the code gos as below for the activity
public class SplashActivity extends Activity{
private final int SPLASH_DISPLAY_LENGHT = 2000;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
/* New Handler to start the Menu-Activity
* and close this Splash-Screen after some seconds.*/
new Handler().postDelayed(new Runnable(){
#Override
public void run() {
/* Create an Intent that will start the Menu-Activity. */
Intent splash2 = new Intent(SplashActivity.this,SplashActivityRed.class);
SplashActivity.this.startActivity(splash2);
SplashActivity.this.finish();
overridePendingTransition(R.anim.fadein,R.anim.fadeout);
}
}, SPLASH_DISPLAY_LENGHT);
}
}
and the xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="#+id/imageViewSplash" android:layout_height="fill_parent" android:layout_width="fill_parent" android:background="#drawable/splash1" android:src="#drawable/splash1"></ImageView>
</LinearLayout>
PS: Sorry I had to hide the text and logo as they come under non-disclosure policy of the company I work for.
Please Remove the imageView from the Layout and add the following line the Linear Layout element
android:background="#drawable/splash1"
Like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background:"#drawable/splash1">
</LinearLayout>
Hope this helps
Also Change the implementation of the SplashScreen with above layout. To change the time line change the value of welcomeScreenDisplay to wotever you want. Currently it is 4 seconds i.e. 4000 mili seconds.
public class SplashScreen extends Activity {
String status, subscriber;
Intent i = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("FIRST");
setContentView(R.layout.splash);
System.out.println("in HOME SCREEN");
/** set time to splash out */
final int welcomeScreenDisplay = 4000;
/** create a thread to show splash up to splash time */
Thread welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {
super.run();
/**
* use while to get the splash time. Use sleep() to increase
* the wait variable for every 100L.
*/
while (wait < welcomeScreenDisplay) {
sleep(100);
wait += 100;
}
} catch (Exception e) {
System.out.println("EXc=" + e);
} finally {
/**
* Called after splash times up. Do some action after splash
* times up. Here we moved to another main activity class
*/
finish();
}
}
};
welcomeThread.start();
}
}
Use this method:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
probably you need to disable the touch event for image. However as remove the imageView from the Layout and add background image to the linear layout element
android:background="#drawable/splash1"