In my app, I have a button to show a drop-down menu, inside of that menu we have some options, one of this is "flip A coin",
the purpose of this option is to flip a coin easy animation, that animation appears inside a textView, and show a head-side or a tail-side of a coin instead of the text in the textView.
I have two problems:
The animation doesn't work how I want, it should appear in 1 second a coin instead of the text inside the textView, it stays there and after 2 seconds he disappears, but after the disappearance, the coin image come back inside the textView, it shouldn't reappear.
This is not a real question for a problem but more an optional question like "you know how to do that?". I 'don't know how to create a flip animation with a coin multiple rotations.
XML drop down menu:
<item
android:id="#+id/flipacoin"
android:title="#string/flipACoin" />
<item
android:id="#+id/rolladice"
android:title="#string/rollADice" />
<item
android:id="#+id/imagebackground"
android:title="#string/changeImage" />
JAVA code that calls the animation function:
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.flipacoin:
flipACoin();
return true;
case R.id.rolladice:
Toast.makeText(this,"TODO roll a dice",Toast.LENGTH_SHORT).show();
return true;
case R.id.imagebackground:
Toast.makeText(this,"TODO image background",Toast.LENGTH_SHORT).show();
return true;
default:
return false;
}
}
JAVA animation function:
public void flipACoin(){
coin.setText(null); //this is for remove the text inside the textView
coin.setBackground(RANDOM.nextFloat() > 0.5f ? getResources().getDrawable(R.drawable.tails) : getResources().getDrawable(R.drawable.heads));
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(2000);
fadeOut.setDuration(1000);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
coin.setAnimation(animation);
}
When You set background at the beginning it just stays after animation. To set back text and background to null You can add Animation listener. Below is sample application which does it:
public class MainActivity extends AppCompatActivity
{
TextView coin;
Random RANDOM;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RANDOM = new Random();
coin = findViewById(R.id.coin);
(findViewById(R.id.click)).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
flipACoin();
}
});
}
public void flipACoin()
{
coin.setText(null);
coin.setBackground(ResourcesCompat.getDrawable(getResources(),
RANDOM.nextFloat() > 0.5f ? R.drawable.ic_launcher_background : R.drawable.ic_launcher_foreground,
null
));
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(2000);
fadeOut.setDuration(1000);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
// listener, it will execute function when animation starts/ends/repeats
animation.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
Log.d("MyTag", "onAnimationStart:");
}
#Override
public void onAnimationEnd(Animation animation) // when animation ends, set text and background to null
{
Log.d("MyTag", "onAnimationEnd:");
coin.setBackground(null);
coin.setText("Default");
}
#Override
public void onAnimationRepeat(Animation animation)
{
Log.d("MyTag", "onAnimationRepeat:");
}
});
coin.setAnimation(animation);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:id="#+id/click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click"
/>
<TextView
android:id="#+id/coin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Default"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
Related
How can I display a message at a specific location in a Google Maps Activity on Android without adding a marker? I just want to display a small pop up animation containing a message at specific coordinates.
Are there any GitHub libraries that can perform this specific task?
You can place any View over MapFragment (or MapView) and animate it as you wish with Animations: animate size, position, transparency etc., use various interpolators and merge several animations into one via AnimatorSet. To get screen position of the View for specific LatLng coordinates you can use Projection.toScreenLocation() method.
For example, for "Hello World" TextView with "popup" animation over the map, you can use code like that:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="activities.MainActivity">
<fragment class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<TextView
android:id="#+id/popup_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:visibility="invisible"
android:text="Hello World!"/>
</RelativeLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private SupportMapFragment mMapSupportedFragment;
private TextView mPopUpTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPopUpTextView = (TextView) findViewById(R.id.popup_view);
mMapSupportedFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_fragment);
mMapSupportedFragment.getMapAsync(MainActivity.this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
// get screen position for latLng
Projection projection = mGoogleMap.getProjection();
Point origin = projection.toScreenLocation(latLng);
// popup TextView
popUpView(origin, mPopUpTextView, 500);
}
});
}
public void popUpView(final Point origin, final View view, long duration){
view.setX(origin.x);
view.setY(origin.y);
view.setVisibility(View.VISIBLE);
ValueAnimator sizeAnimation = ValueAnimator.ofInt(0, view.getMeasuredHeight());
sizeAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
sizeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = val;
view.setLayoutParams(layoutParams);
}
});
sizeAnimation.setDuration(duration);
ValueAnimator positionAnimation = ValueAnimator.ofInt(0, view.getMeasuredHeight());
positionAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
positionAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
view.setY(origin.y - val);
}
});
positionAnimation.setDuration(duration);
AnimatorSet popUpSet = new AnimatorSet();
popUpSet.play(sizeAnimation).with(positionAnimation);
popUpSet.start();
}
}
Result:
I would suggest you go with marker only.
As marker it self gives some features like animation and all.
You can also customize the marker in different way to show the text and not the image and also you can user the customized text like html text show more decorated text backed by html and css.
This one is simple and great solution as i have also used the same in of my project.
I am brand new to Android Studio and am trying to figure out how to change the background color of my start up app.
The moment the app loads, I see a button on the screen, and when I click, it goes to the color red.
What I want is when you click the button, it goes from red to green to blue than back to red.
However, I keep getting these errors:
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.
Error:(72, 9) error: class, interface, or enum expected
Main Activity XML File:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/layout">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Color"
android:onClick="onChangeColor"/>
</LinearLayout>
Test Activity Java Code:
private int colorIndex = 1;
public void onChangeColor(View view) {
int color;
if(colorIndex==0) {
color = Color.RED;
colorIndex = 1;
}else if(colorIndex==1) {
color = Color.GREEN;
colorIndex = 2;
}else {
//colorIndex = 2
color = Color.BLUE;
colorIndex = 0;
}
View layout = findViewById(R.id.layout);
layout.setBackgroundColor(color);
}
public class TestActivity extends AppCompatActivity {
View view;
//declare a string variable in java a class
//private var colour = "green";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View layout = findViewById(R.id.layout);
layout.setBackgroundColor(Color.RED);
view= this.getWindow().getDecorView();
view.setBackgroundResource(R.color.gray);
}
public void goRed(View v)
{
//if (colour == "green"){
view.setBackgroundResource(R.color.red);
//colour = "red";
//}
}
}
To give you a excellent help, it will be necessary to see you code.
Any way if i andersted you right maybe this will help you :
On your xml layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/layout">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Color"
android:onClick="onChangeColor"/>
</LinearLayout>
On your activity :
private int colorIndex = 1;
public void onChangeColor(View view) {
int color;
if(colorIndex==0) {
color = Color.RED;
colorIndex = 1;
}else if(colorIndex==1) {
color = Color.GREEN;
colorIndex = 2;
}else {
//colorIndex = 2
color = Color.BLUE;
colorIndex = 0;
}
View layout = findViewById(R.id.layout);
layout.setBackgroundColor(color);
}
On you onCreate in the activity
View layout = findViewById(R.id.layout);
layout.setBackgroundColor(Color.RED);
If I understood correctly what you want is, to transition over a series of colours over time, and each colour lasting for some 1-2 seconds. You can use Android's default CountDownTimer.
Keep Your xml layout same.
In your Activity:
public class TestActivity extends AppCompatActivity {
LinearLayout layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (LinearLayout)findViewById(R.id.layout);
layout.setBackgroundColor(Color.RED);
}
public void onChangeColor(View view) {
// start your timer on button click
new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
changeBackground(3-millisUntilFinished/1000);
}
}.start();
}
private void changeBackground(int colorIndex){
int color;
if(colorIndex==1) {
color = Color.GREEN;
}else if(colorIndex==2) {
color = Color.BLUE;
}else {
color = Color.RED;
}
layout.setBackgroundColor(color);
}
}
Hope this might help. If I misunderstood something please comment.
Edit: I typecasted View to LinearLayout
Imagine a number 10, then after user clicks a button it changes to 100. But how to make an efficient transition
10 -> 100,
that will display values like
12, 15, 18, ..., 97, 100 over 1 second.
I've seen something like that in "Cookie clicker" but couldn't find anything about that kind of transition in the source code.
I had an idea of a loop (for number1 < number2, do number1++), it will work fine for small numbers, but if 10 changes to 1 billion, then the loop will probably freeze the whole app.
Second idea is to get added value (100-10=90) and divide by 30 or 60 frames, and add this value with each frame. But what will happen if frame is dropped? - Probably value will not be added. What if user makes double click or the system adds values automatically?
Hope it gives an idea of what kind of number transition I need.
Maybe I overlooked and there is a simple approach? Any help is appreciated.
Hope this little demo using a ValueAnimator will inspire you to find an appropriate solution.
You can specify the duration of the animation (see code) and even adjust the frame-rate by saying mAnimator.setFrameDelay(frameDelay);.
By using animator.isRunning() or animator.isStarted() you can prevent double-click malfunction or other unwanted behaviour while the current animation is runnning.
The Main Activity:
/** ValueAnimator demo */
public class MainActivity extends Activity {
ValueAnimator mAnimator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tv = (TextView) findViewById(R.id.textview);
mAnimator = ValueAnimator.ofInt(1, 100).setDuration(1000);
mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
final Integer value = (Integer) animator.getAnimatedValue();
tv.setText(String.format("%04d", value));
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animator) {
super.onAnimationEnd(animator);
final int endValue = Integer.parseInt((String) tv.getText());
mAnimator.setIntValues(endValue, endValue + 100);
}
});
}
/** Button callback */
public void onClick(final View view) {
if (!mAnimator.isStarted() && !mAnimator.isRunning()) {
mAnimator.start();
}
}
}
Simple demo layout:
<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:orientation="vertical" >
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:typeface="monospace"
android:text="0001" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gimme +100"
android:onClick="onClick">
</Button>
Here's another demo (hope this answers your 2. question), which implements different behaviour dependent on single click or double-click on the button. Just experiment with it, you now have the basic building blocks to construct own behavour ...
/** ValueAnimator demo */
public class MainActivity extends Activity {
ValueAnimator mAnimator;
TextView mTv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTv = (TextView) findViewById(R.id.textview);
mAnimator = ValueAnimator.ofInt(1, 100).setDuration(1000);
mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(final ValueAnimator animator) {
final Integer value = (Integer) animator.getAnimatedValue();
mTv.setText(String.format("%04d", value));
}
});
final Button button = (Button) findViewById(R.id.button);
final GestureDetector gestureDetector = new GestureDetector(this,
new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDoubleTap(MotionEvent e) {
performAnimation(100);
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
performAnimation(0);
return true;
}
});
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
});
}
/** starts animation */
private void performAnimation(final int offset) {
if (!mAnimator.isStarted() && !mAnimator.isRunning()) {
final int endValue = Integer.parseInt((String) mTv.getText());
mAnimator.setIntValues(endValue + offset, endValue + 100 + offset);
mAnimator.start();
}
}
}
Don't forget to replace your layout file, since the click-attribute of the button has been removed:
<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:orientation="vertical" >
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:typeface="monospace"
android:text="0001" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Gimme +100" >
</Button>
</LinearLayout>
I guess you can do it by using different threads. Only main thread works with UI so you can divide the interval into small intervals and make a transitions in different threads.After send them to main thread and print. Hope it will help.
On one hand I have a layout with two ImageView :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/image_cross2"
android:layout_width="wrap_content"
android:layout_height="#dimen/image_size"
android:layout_gravity="top"
android:scaleType="centerCrop" />
<ImageView
android:id="#+id/image_cross1"
android:layout_width="wrap_content"
android:layout_height="#dimen/image_size"
android:layout_gravity="top"
android:scaleType="centerCrop" />
</FrameLayout>
On the other hand i have a list of image ressources :
static int mImages[] = new int[] {
R.drawable.artistes,
R.drawable.couple1,
R.drawable.couple2,
R.drawable.couple3,
R.drawable.enfant,
R.drawable.manege,
R.drawable.manege2,
R.drawable.metropolitain,
R.drawable.panoramique,
R.drawable.sacrecoeur };
i have also a Scheduler made from Handler + postDelayed() to display the images one after another with a timer. This is working fine
my issue is about the transition animation from one imageview to the other, knowing that i have to clean the imageviews each time to avoid OutOfMemoryExceptions :
For now i do that in the schduled callback method :
if (mIndex == mImages.length) {
mIndex = 0; // repeat
}
if (mIndex % 2 != 0) { // pair
mImageCross2.setImageResource(mImages[mIndex++]);
Utils.crossfade(mImageCross2, mImageCross1, 1000/*duration*/);
mImageCross1.setImageResource(0);
} else {
mImageCross1.setImageResource(mImages[mIndex++]);
Utils.crossfade(mImageCross1, mImageCross2, 1000);
mImageCross2.setImageResource(0);
}
with this animation :
public static void crossfade(final ImageView viewIn, final ImageView viewOut, int duration) {
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(duration);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setDuration(duration);
fadeOut.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
viewOut.setVisibility(View.GONE);
}
});
fadeIn.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
viewIn.setVisibility(View.VISIBLE);
}
});
viewOut.startAnimation(fadeOut);
viewIn.startAnimation(fadeIn);
}
The animation is not great, the fade is not really smooth, what can i do to make it more smooth while having to clean the ImageView each times ?
My first suggestion is to simplify most of your code. Android has this nice little class called TransitionDrawable
so you can have just 1 image view and use the TransitionDrawable:
TransitionDrawable td = new TransitionDrawable( new Drawable[] {
getResources().getDrawables(mImages[x]),
getResources().getDrawables(mImages[y])
});
imageView.setImageDrawable(td);
and call the animation on td with
td.startTransition(1000);
// and
td.reverseTransition(1000);
and keep using the postDelayed to trigger them
I'm making an app that just displays a clock, but I want is so that everytime a user touches the screen it changes the color of the text (from a list of preselected colors in a colors.xml file) but I haven't got a clue where to start. Can someone point me in the right direction?
Here's the main activity:
public class MainActivity extends Activity {
private static final Random RANDOM = new Random();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
Handler handler = new RandomMoveHandler((TextView) findViewById(R.id.digitalClock1));
handler.sendEmptyMessage(0);
}
// Make the handler subclass static because of this: http://stackoverflow.com/a/11408340/111777
private static class RandomMoveHandler extends Handler {
private final WeakReference<TextView> textViewWeakReference;
private RandomMoveHandler(TextView textView) {
this.textViewWeakReference = new WeakReference<TextView>(textView);
}
#Override
public void handleMessage(Message msg) {
TextView textView = textViewWeakReference.get();
if (textView == null) {
Log.i(TAG, "WeakReference is gone so giving up.");
return;
}
int x = RANDOM.nextInt(350 - 100);
int y = RANDOM.nextInt(800 - 100);
Log.i(TAG, String.format("Moving text view to (%d, %d)", x, y));
textView.setX(x);
textView.setY(y);
//change the text position here
this.sendEmptyMessageDelayed(0, 30000);
}
}
private static final String TAG = MainActivity.class.getSimpleName();
}
and here's the layout xml:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity"
android:background="#color/black" >
<DigitalClock
android:id="#+id/digitalClock1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DigitalClock"
android:textColor="#color/ics_blue"
android:textSize="28sp" />
I haven't making deal with DigitalClock but I think, at first, you should reference DigitalClock variable, not TextView. And second, to intercept touch event you need to override onTouckEvent method of your activity, it will callback everytime user touches the screen.
You should follow these steps
Use a TimerTask to.continusly show the time
Implement a touchlistener on that clock view
like this
view.setOnTouchListener
Make an array Colors like this
int[] colr={Color.BLACK,Color.BLUE};
and use random index in your touch event andset it as your color of the view