Fragment parent layout transparent - android

I use circularRevealAnimation to start one of Fragments. Here's its layout.
<?xml version="1.0" encoding="utf-8"?>
<io.codetail.widget.RevealFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/main_container"
android:background="#color/red"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/container2"
android:layout_width="match_parent"
android:background="#color/white"
android:layout_height="match_parent"
android:orientation="vertical">
....
</LinearLayout>
</io.codetail.widget.RevealFrameLayout>
In my Fragment class I trigger revealAnimation in onStart() method.
#Override
public void onStart() {
super.onStart();
// SupportAnimator animator = ViewAnimationUtils.createCircularReveal(container2, 720, 0, 0, 1386); ->line from onCreateView
animator.setDuration(500);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
animator.addListener(new SupportAnimator.AnimatorListener() {
#Override
public void onAnimationStart() {
System.out.println("lol222");
}
#Override
public void onAnimationEnd() {
System.out.println("end");
}
#Override
public void onAnimationCancel() {
}
#Override
public void onAnimationRepeat() {
}
});
}
As you see, the parent layout has red color, when its child is white. When I started this Fragment I can see white circularReveal over the red background, when I want to see such animator over previous fragment. How can I achieve this?
I tried to make background="#null" and so on, while reading SOF related topics. Nothing helped me. So what is write way to setFragmentparentlayoutastransparent`?

You can implement using xml like this
android:background="#android:color/transparent"
or programatically you can change like this
yourview.setBackgroundColor(Color.parseColor("#00000000"));

There was my fault. My container was LinearLayout, not FrameLayout. Bacause of that there wasn't transparency.

Related

onAnimationEnd is not getting called for imageview rotation animation

I have two ImageViews, one is rotating clockwise & other anti-clockwise.
Same code is working for other animation but for rotation, onAnimationEnd is not getting called.
onAnimationEnd is not getting called here.
public class ObcActivity extends AppCompatActivity implements Animation.AnimationListener {
ImageView circularImageView1;
ImageView circularImageView2;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.activity_obc);
// setContentView( new HeartbeatView(this));
clockAnimation=AnimationUtils.loadAnimation(this, R.anim.rotate_clockwise);
antiClockAnimation =AnimationUtils.loadAnimation(this, R.anim.rotate_anticlockwise);
clockAnimation.setAnimationListener(this);
antiClockAnimation.setAnimationListener(this);
clockAnimation.setRepeatCount(-1);
antiClockAnimation.setRepeatCount(-1);
clockAnimation.setRepeatMode(Animation.INFINITE);
antiClockAnimation.setRepeatMode(Animation.INFINITE);
circularImageView1= (ImageView) findViewById(R.id.circularImageView1);
circularImageView2= (ImageView) findViewById(R.id.circularImageView2);
circularImageView1.setAnimation(clockAnimation);
circularImageView1.startAnimation(clockAnimation);
circularImageView2.setAnimation(antiClockAnimation);
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Toast.makeText(this,""+System.currentTimeMillis(),Toast.LENGTH_SHORT).show();
if(animation==clockAnimation){
circularImageView1.setVisibility(View.INVISIBLE);
circularImageView2.setVisibility(View.VISIBLE);
circularImageView1.clearAnimation();
circularImageView2.startAnimation(clockAnimation);
}else {
circularImageView2.setVisibility(View.INVISIBLE);
circularImageView1.setVisibility(View.VISIBLE);
circularImageView1.startAnimation(antiClockAnimation);
circularImageView2.clearAnimation();
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
Animation clockAnimation, antiClockAnimation;
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#71bf44"
android:orientation="vertical">
<ImageView
android:id="#+id/circularImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/ic_circle"
/>
<ImageView
android:id="#+id/circularImageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/outer_ring_2_white"
/>
<ImageView
android:id="#+id/circularImageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/outer_ring_3_white"
/>
<ImageView
android:id="#+id/circularImageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/outer_ring_2_white_out"
/>
<ImageView
android:id="#+id/circularImageView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:src="#drawable/outer_ring_3_white_out"
/>
</RelativeLayout>
Update:
As per the answers, I set following code which is not working, not calling onAnimationEnd. I need to get event of when animation of first image ends!
clockAnimation.setRepeatCount(100);
antiClockAnimation.setRepeatCount(100);
clockAnimation.setRepeatMode(100);
antiClockAnimation.setRepeatMode(100);
Because you have set INFINITE in Animation
clockAnimation.setRepeatMode(Animation.INFINITE);
it will start with infinite mode means never End
Your animation iteration updatation will notify in onAnimationRepeat
#Override
public void onAnimationRepeat(Animation animation) {
}
What document saying of method onAnimationEnd
Notifies the end of the animation. This callback is not invoked for
animations with repeat count set to INFINITE.
as per comment:
But I need animation end event. for example after 2 rotations.
for that add this lines in code
clockAnimation.setRepeatCount(2);
clockAnimation.setRepeatMode(Animation.RESTART);
Have a look at the documentation for INFINITE animations:
void onAnimationEnd (Animation animation)
Notifies the end of the animation. This callback is not invoked for
animations with repeat count set to INFINITE.
In any event I suggest holding two Animation.AnimationListener objects and implementing one in your activity. This would make your code clearer and remove the need to ask questions like if(animation==clockAnimation).

Get height of child layout (including child elements) in onCreateView of fragment

The size of a layout i'm using in a fragment is always 0.
I have a fragment that includes a child-layout that looks like this:
<RelativeLayout android:id="#+id/animationLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="30dp"
android:background="#color/colorPrimary"
android:elevation="4dp">
This layout has a child-layout that is defined like this:
<TableLayout android:id="#+id/searchForm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="0"
android:background="#color/colorPrimary"
android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true">
[Some Child elements]
</TableLayout>
In the onCreateView of the parent fragment, the height of the layout 'searchForm' is always 0.
Even if i measure the size in
searchForm.post(new Runnable() {
#Override
public void run() {
searchFormHeight = searchForm.getHeight(); //always 0
}
}
the size is 0.
How can i get the size of this layout in onCreateView?
You need to use a ViewTreeListener for a callback when the entire view is inflated. If I recall android waits for the entire view to be inflated at once, so even if a view is instaniated, it may not be inflated returning a height of 0.
searchForm.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw () {
searchFormHeight = searchForm.getHeight();
return true;
});
Ok, i don't know what i've done wrong before, but finally following worked for me:
searchForm.post(new Runnable() {
#Override
public void run() {
searchFormHeight = searchForm.getHeight();
}
});
Actually onCreateView() process the creation of view that's why it return 0
Try following to get height, override function into fragment class
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
searchFormHeight = searchForm.getHeight();
}

Animations get into infinite loop if they are started in the onAnimationEnd of AnimationListener

Simple task: by pressing button, it scales X value to 0, and when animation finished starts another animation on the second view which scales X from 0 to 1. After 1 second reverse animation should be played and that's all. Running code below I've got infinite animation loop of the first part of animation.
Used nineoldandroids lib, but I don't think this is something really different from native animations framework at least on jelly bean devices.
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View mybutton = findViewById(R.id.mybutton);
final View myprogress = findViewById(R.id.myprogress);
mybutton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
animate(mybutton).scaleX(0).setListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
mybutton.setVisibility(View.INVISIBLE);
myprogress.setVisibility(View.VISIBLE);
ViewHelper.setScaleX(myprogress, 0f);
animate(myprogress).scaleX(1).setListener(new AnimatorListenerAdapter()
{
#SuppressWarnings("ConstantConditions")
#Override
public void onAnimationEnd(Animator animation)
{
mybutton.getHandler().postDelayed(new Runnable()
{
#Override
public void run()
{
animate(myprogress).scaleX(0).setListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
myprogress.setVisibility(View.INVISIBLE);
mybutton.setVisibility(View.VISIBLE);
ViewHelper.setScaleX(mybutton, 0);
animate(mybutton).scaleX(1);
}
});
}
}, 1000);
}
});
}
});
}
});
}
}
Layout is simple:
<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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/mycontainer">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="string text"
android:id="#+id/mybutton"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#id/mybutton"
android:layout_alignTop="#id/mybutton"
android:layout_alignRight="#id/mybutton"
android:layout_alignBottom="#id/mybutton"
android:visibility="invisible"
android:id="#+id/myprogress"
/>
</RelativeLayout>
</RelativeLayout>
Where I was wrong?
Madness!
After investigation found source of it:
When animate() method called, it creates ViewPropertyAnimator and saves it to the map.
When you try to animate this view again with animate() it takes already created viewpropertyanimator from the map and immediately calls onAnimationStart() even before you set new animation parameters, and because animationlistener was set on the first animation, it was triggered! and launched first animation(second part of it). This is creates infinite loop.
To stop it you MUST clear old listener when you try to animate view second time, so
animate(mybutton).setListener(null).scaleX(1);
stops infinite loop.
Documentation should warn about it, definitely!

How to animate a slide in notification view that pushes the content view down

I have two views on the screen
one sits at the top of the screen and on sits directly below it
I need the green view to slide out the top - and make the blue view take up the entire screen as a result
this is what i am trying to do:
-- the problem is , when the animation is finished, the blue view just "jumps" up - and i want it to ease up with the disappearing green view, how do i do that?
slide_in_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromYDelta="-100%"
android:toYDelta="0%" />
</set>
slide_out_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromYDelta="0%"
android:toYDelta="-100%" />
</set>
MainActivity.java
slideInAnimation = AnimationUtils.loadAnimation(mActivity, R.anim.slide_in_animation);
slideOutAnimation = AnimationUtils.loadAnimation(mActivity,R.anim.slide_out_animation);
slideInAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mGreenView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
}
});
slideOutAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mGreenView.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) {
// To change body of implemented methods use File | Settings
// | File Templates.
}
});
This worked for me
First you must import this library: http://nineoldandroids.com/
The import is done by importing existing android project into your workspace, afterwards right click your Poject -> Properties -> Android. Here you will see a library section, click the Add button and add the nineoldandroids library.
First off, here is the layout xml used for this to work:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:divider="#android:color/transparent"
android:fastScrollEnabled="false"
android:listSelector="#android:color/transparent"
android:scrollbars="vertical"
android:smoothScrollbar="true" />
<View
android:id="#+id/greenView"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#ff00ff00"
android:alpha="0"/>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/animate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickHandler"
android:text="animate" />
<Button
android:id="#+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickHandler"
android:text="close" />
</LinearLayout>
Notice: Both the ListView and the green View could be layouts of any types with any kind of content.
And next a proof of concept Activity.
public class TestActivity extends Activity {
private View greenView;
private ListView listView;
private int greenHeight;
private boolean isShowingBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
// The animated view
greenView = (View)findViewById(R.id.greenView);
listView = (ListView)findViewById(R.id.listView1);
// Instanciating an array list (you don't need to do this, you already have yours)
ArrayList<String> your_array_list = new ArrayList<String>();
your_array_list.add("1");
your_array_list.add("2");
your_array_list.add("3");
your_array_list.add("4");
your_array_list.add("5");
your_array_list.add("6");
your_array_list.add("7");
your_array_list.add("8");
your_array_list.add("9");
your_array_list.add("10");
your_array_list.add("11");
your_array_list.add("12");
your_array_list.add("13");
your_array_list.add("14");
your_array_list.add("15");
// This is the array adapter, it takes the context of the activity as a first // parameter, the type of list view as a second parameter and your array as a third parameter
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, your_array_list);
listView.setAdapter(arrayAdapter);
final LinearLayout layout = (LinearLayout)findViewById(R.id.parentLayout);
final ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < 16) {
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
greenHeight = greenView.getHeight();
}
});
}
public void clickHandler(View v) {
if (isShowingBox) {
isShowingBox = false;
slideOut(1500, 0);
} else {
isShowingBox = true;
slideIn(1500, 0);
}
}
private void slideIn(int duration, int delay) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
// animate from off-screen in to screen
ObjectAnimator.ofFloat(greenView, "translationY", -greenHeight, 0),
ObjectAnimator.ofFloat(listView, "translationY", 0, greenHeight),
ObjectAnimator.ofFloat(greenView, "alpha", 0, 0.25f, 1)
// add other animations if you wish
);
set.setStartDelay(delay);
set.setDuration(duration).start();
}
private void slideOut(int duration, int delay) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
// animate from on-screen and out
ObjectAnimator.ofFloat(greenView, "translationY", 0, -greenHeight),
ObjectAnimator.ofFloat(listView, "translationY", greenHeight, 0),
ObjectAnimator.ofFloat(greenView, "alpha", 1, 1, 1)
// add other animations if you wish
);
set.setStartDelay(delay);
set.setDuration(duration).start();
}
}
Important note: Remember to import the AnimatorSet and ObjectAnimator from nineoldandroids in your class and not the Android SDK ones!!!
One potential solution that makes a nice and fluid exit is using the weight attribute of LinearLayout with a ValueAnimator. Assuming you're using LinearLayout as your parent view for your green and blue blocks, your code would look something like this.
layout.xml
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!--Let's assume this is the view you wish you disappear-->
<View
android:id="#+id/view1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"/>
<View
android:id="#+id/view2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
Now with this, in your code you can use the ValueAnimator as follows:
public class MainActivity extends Activity implements AnimatorUpdateListener
{
View view1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
view1 = (View)findViewById(R.id.view1);
}
public void someAction()
{
//This is the important part, because it is FROM the first value TO
//the second. Notice that it must be a float type
ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
anim.setDuration(200);
anim.addUpdateListener(this);
anim.start();
}
#Override
public void onAnimationUpdate(ValueAnimator animation)
{
view1.setLayoutParams(new LinearLayout.LayoutParams(0,
LayoutParams.MATCH_PARENT,
(Float) animation.getAnimatedValue()));
}
}
The ValueAnimator will automatically calculate the increments and execute them to get the smooth transition you want with the added benefit of keeping your view running.
You may also need to handle some strange UI occurrences as a result of shrinking the view (i.e., TextViews may act funny on the transition out), but I didn't run into too much trouble patching those up and keeping it neat.
Good luck! Hope this helps.
Use following code.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>

View over Canvas Visibility issue

I have this layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.components.game.GameView
android:id="#+id/game_id"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:id="#+id/ChatLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="invisible"
android:focusable="true"
android:focusableInTouchMode="true" >
<Button
android:id="#+id/ChatCancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="X" />
<Button
android:id="#+id/ChatOkButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="OK" />
<EditText
android:id="#+id/ChatEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/ChatOkButton"
android:layout_toRightOf="#+id/ChatCancelButton"
android:maxLength="50"
android:singleLine="true" />
</RelativeLayout>
</RelativeLayout>
It's a RelativeLayout over a canvas. At start time it's invisible but when a user clicks a button the layout should become visible.
The problem is that it's not becoming visible. The layout is there but it's just not drawing it. If I press the position where the layout should appear it receives the event and opens the keyboard but it's not drawing the whole layout.
What is the problem?
If I set the RelativeLayout to visible at the beginning it works fine. it shows the layout and if I toggle between invisible and visible it works fine.
I made a workaround that almost always works.
I start the layout visible and than do that in the oncreate:
chatLayout.postDelayed(new Runnable() {
#Override
public void run() {
chatLayout.setVisibility(View.INVISIBLE);
}
}, 50);
But I don't like it and want to understand what's the problem.
The code:
It starts from a canvas button which send a message to a handler:
public void showInputLayout() {
Message.obtain(gameHandler, SHOW_INPUT_LAYOUT).sendToTarget();
}
In the handler:
case SHOW_INPUT_LAYOUT:
gameActivity.setChatVisibility(true);
break;
setChatVisibility:
public void setChatVisibility(boolean isVisible) {
int visible = isVisible ? View.VISIBLE : View.INVISIBLE;
chatLayout.setVisibility(visible);
if(isVisible){
chatEditText.setFocusable(true);
chatEditText.requestFocus();
}
}
Add a click listener to RelativeLayout and switch the visibility between GONE and VISIBLE. Try something like this:
int visibility = View.VISIBLE;
RelativeLayout layout = (RelativeLayout)findViewById(R.id.ChatLayout);
layout.setVisibility(visibility);
layout.setOnClickListener(new View.OnClickListener{
public void onClick(View v)
{
if(visibility == View.VISIBLE)
visibility = View.GONE;
else
visibility = View.VISIBLE;
v.setVisibility(visibility);
}
})
I ran into a similar issue recently, and for my case the problem was actually in the onDraw() method of the view underneath (should be com.components.game.GameView in your case). See if you can add calls to Canvas' getSaveCount(), save() and restoreToCount() in your drawing code, similar to this:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int saveCount = canvas.getSaveCount();
canvas.save();
// custom drawing code here ...
// use Region.Op.INTERSECT for adding clipping regions
canvas.restoreToCount(saveCount);
}
I believe what happened was that sometimes the framework set the clipping regions for the elements on top of our Canvas-drawing widget before our onDraw() method is called so we need to make sure that those regions are preserved.
Hope this helps.

Categories

Resources