Invert reveal transition animation - java

Based from this example
I created a fab using the support design library to re create the same action. The reveal and the fab animation works well but now i've got 2 problems:
1) My fab contains an icon. When the fab start the animation (like in the gif) the icon become shelled because it change the scaleX and scaleY. So is there a way to prevent this?
2) The example creates the animation but it doesn't explain how invert the reveal.. I would that onKeyDown() the content reveled go back and appears again the fab.
This is the github project https://github.com/saulmm/Curved-Fab-Reveal-Example
and here the code i use:
For first my fab in the layout:
<FrameLayout
android:id="#+id/fab_container"
android:layout_below="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="-30dp"
android:elevation="2dp"
>
<include
android:id="#+id/voice_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
layout="#layout/voice_content_layout" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/myFAB"
android:transitionName="button_fab"
app:backgroundTint="#color/colorAccent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_mic_white_24dp"
app:elevation="2dp"
app:borderWidth="0dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:layout_gravity="bottom|right"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:onClick="onFabPressed" />
</FrameLayout>
Here's the rest of java code:
public void onFabPressed(View view) {
final float startX = myFab.getX();
AnimatorPath path = new AnimatorPath();
path.moveTo(0, 0);
path.curveTo(-200, 200, -400, 100, -600, 50);
final ObjectAnimator anim = ObjectAnimator.ofObject(this, "fabLoc",
new PathEvaluator(), path.getPoints().toArray());
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(ANIMATION_DURATION);
anim.start();
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
if (Math.abs(startX - myFab.getX()) > MINIMUN_X_DISTANCE) {
if (!mRevealFlag) {
mFabContainer.setY(mFabContainer.getY() + mFabSize / 2);
myFab.animate()
.scaleXBy(SCALE_FACTOR)
.scaleYBy(SCALE_FACTOR)
.setListener(mEndRevealListener)
.setDuration(ANIMATION_DURATION);
mRevealFlag = true;
}
}
}
});
}
private AnimatorListenerAdapter mEndRevealListener = new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myFab.setVisibility(View.INVISIBLE);
mFabContainer.setBackgroundColor(getResources().getColor(R.color.colorAccent));
for (int i = 0; i < voiceContentLayout.getChildCount(); i++) {
View v = voiceContentLayout.getChildAt(i);
ViewPropertyAnimator animator = v.animate()
.scaleX(1).scaleY(1)
.setDuration(ANIMATION_DURATION);
animator.setStartDelay(i * 50);
animator.start();
}
}
};
/**
* We need this setter to translate between the information the animator
* produces (a new "PathPoint" describing the current animated location)
* and the information that the button requires (an xy location). The
* setter will be called by the ObjectAnimator given the 'fabLoc'
* property string.
*/
public void setFabLoc(PathPoint newLoc) {
myFab.setTranslationX(newLoc.mX);
if (mRevealFlag)
myFab.setTranslationY(newLoc.mY - (mFabSize / 2));
else
myFab.setTranslationY(newLoc.mY);
}

Related

Animation doesn't end - Android

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>

Transition between decimal or double numbers

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.

Animated transition between two imageview

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

Android Custom View always getting 0 width when calling onMeasure

I'm fairly new to android dev and am trying to learn ropes. In order to do that I've been messing around Custom Views in android. I am trying to build an alarm clock app and I want to make a nice spinner to select the times from. Similar to say this:
http://i47.tinypic.com/aymyjc.jpg
I have created an AndroidScollSpinner class that looks like this:
public class AndroidScrollSpinner extends View {
public AndroidScrollSpinner(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBackground(canvas);
drawSomeText(canvas);
canvas.restore();
}
private void drawSomeText(Canvas canvas) {
Paint titlePaint = new Paint();
titlePaint.setColor(Color.BLUE);
canvas.drawTextOnPath("Bert", new Path(), 0.0f,0.0f, titlePaint);
}
private void drawBackground(Canvas canvas) {
Paint backgroundPaint = new Paint();
backgroundPaint.setColor(getResources().getColor(R.color.bluegrass));
backgroundPaint.setStyle(Paint.Style.FILL);
Bitmap background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
canvas.drawBitmap(background, 0, 0, backgroundPaint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
int h = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(w, h);
}
}
The issue I am having is in the onMeasure
The MeasureSpec.getSize(widthMeasureSpec) always returns 0. Does anyone know why? Or what I am missing here?
Here's my layout file as well.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:id="#+id/addAlarmSpinnerLayout">
</LinearLayout>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
<ToggleButton android:id="#+id/sundayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/S"
android:textOff="#string/S"/>
<ToggleButton android:id="#+id/mondayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/M"
android:textOff="#string/M"/>
<ToggleButton android:id="#+id/tuesdayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/T"
android:textOff="#string/T"/>
<ToggleButton android:id="#+id/wednesdayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/W"
android:textOff="#string/W"/>
<ToggleButton android:id="#+id/thursdayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/T"
android:textOff="#string/T"/>
<ToggleButton android:id="#+id/fridayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/F"
android:textOff="#string/F"/>
<ToggleButton android:id="#+id/saturdayToggleButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.14"
android:textOn="#string/S"
android:textOff="#string/S"/>
</LinearLayout>
<Button android:id="#+id/doneButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/done"
android:onClick="onDoneClicked">
</Button>
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hour24Clock"
android:id="#+id/hour24switch"
android:layout_gravity="center"
android:enabled="true"
android:onClick="createSpinners"/>
</LinearLayout>
If you need to know anything else about the app, have a look here under https://github.com/rdsmallwood928/NeverLate
Also I do realize that there probably third party libraries out there that I can use to get the spinner effect that I want. However, I'm really doing this as a learning exercise so it more important to me to understand why this code always returns 0 than to inject a custom component from somewhere else and get on with my life. Thanks in advance for your help!
EDIT: Here is the AddAlarmFragment class that creates the spinners
public class AddAlarmFragment extends Fragment {
private AndroidClickSpinner minuteSpinner;
private AndroidClickSpinner hourSpinner;
private AndroidClickSpinner amPmSpinner;
private ToggleButton mondayToggle;
private ToggleButton tuesdayToggle;
private ToggleButton wednesdayToggle;
private ToggleButton thursdayToggle;
private ToggleButton fridayToggle;
private ToggleButton saturdayToggle;
private ToggleButton sundayToggle;
private Switch hour24Switch = null;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.add_alarm, container, false);
}
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
createSpinners(view);
}
#Override
public void onResume() {
super.onResume();
}
public void createSpinners(View view) {
LinearLayout layout = (LinearLayout) view.findViewById(R.id.addAlarmSpinnerLayout);
hour24Switch = (Switch) view.findViewById(R.id.hour24switch);
layout.removeAllViews();
ArrayList<Object> hours = new ArrayList<>();
if(hour24Switch.isChecked()) {
for(int i=0;i<24;i++) hours.add(i);
} else {
for(int i=1;i<=12;i++) hours.add(i);
}
hourSpinner = new AndroidClickSpinner(getActivity(), hours);
layout.addView(hourSpinner);
ArrayList<Object> minutes = new ArrayList<>();
for(int i=0;i<=60;i++) minutes.add(i);
minuteSpinner = new AndroidClickSpinner(getActivity(), minutes);
layout.addView(minuteSpinner);
if(!hour24Switch.isChecked()) {
ArrayList<Object> amPm = new ArrayList<>();
amPm.add("AM");
amPm.add("PM");
amPmSpinner = new AndroidClickSpinner(getActivity(), amPm);
layout.addView(amPmSpinner);
}
mondayToggle = (ToggleButton) view.findViewById(R.id.mondayToggleButton);
tuesdayToggle = (ToggleButton) view.findViewById(R.id.tuesdayToggleButton);
wednesdayToggle = (ToggleButton) view.findViewById(R.id.wednesdayToggleButton);
thursdayToggle = (ToggleButton) view.findViewById(R.id.thursdayToggleButton);
fridayToggle = (ToggleButton) view.findViewById(R.id.fridayToggleButton);
saturdayToggle = (ToggleButton) view.findViewById(R.id.saturdayToggleButton);
sundayToggle = (ToggleButton) view.findViewById(R.id.sundayToggleButton);
//Prevent no day selected...
switch (new LocalDate().getDayOfWeek()) {
case 1:
mondayToggle.setSelected(true);
break;
case 2:
tuesdayToggle.setSelected(true);
break;
case 3:
wednesdayToggle.setSelected(true);
break;
case 4:
thursdayToggle.setSelected(true);
break;
case 5:
fridayToggle.setSelected(true);
break;
case 6:
saturdayToggle.setSelected(true);
break;
case 7:
sundayToggle.setSelected(true);
break;
}
PieChart pie = new PieChart(getActivity());
Resources res = getResources();
pie.addItem("Agamemnon", 2, res.getColor(R.color.seafoam));
pie.addItem("Bocephus", 3.5f, res.getColor(R.color.chartreuse));
pie.addItem("Calliope", 2.5f, res.getColor(R.color.emerald));
pie.addItem("Daedalus", 3, res.getColor(R.color.bluegrass));
pie.addItem("Euripides", 1, res.getColor(R.color.turquoise));
pie.addItem("Ganymede", 3, res.getColor(R.color.slate));
layout.addView(pie);
layout.addView(new AndroidScrollSpinner(getActivity()));
}
public Integer getHours() {
Integer hour = Integer.parseInt(hourSpinner.getSelectedItem().toString());
if(!hour24Switch.isChecked()) {
if(hour == 12) {
hour = 0;
}
if(amPmSpinner.getSelectedItem().equals("PM")) {
hour = hour + 12;
}
}
return hour;
}
public Integer getMinutes() {
return Integer.parseInt(minuteSpinner.getSelectedItem().toString());
}
public boolean[] getDays() {
boolean[] days = new boolean[7];
days[0] = mondayToggle.isChecked();
days[1] = tuesdayToggle.isChecked();
days[2] = wednesdayToggle.isChecked();
days[3] = thursdayToggle.isChecked();
days[4] = fridayToggle.isChecked();
days[5] = saturdayToggle.isChecked();
days[6] = sundayToggle.isChecked();
return days;
}
}
I'm sorry, but where in your layout you are using it ?
Are you adding it from code, since I couldn't see it included somewhere in your XML layout file

How to create an expandable list?

I need to create Collapse / Expand forms in Android. I am thinking about using either RelativeLayout or TableLayout for this purpose. But, what XML element make these forms expand and hide in android?
If you are not sure what I am not talking about, take an application like Sales Force for an example. There you have these expandable menus in all the forms. How can I do this?
Following is an example (taken from Sales Force)
When you expand these, it looks like below
You could do the following. create a layout that has the following:
1. A Heading or a textview with the label contacts
2. Below it a layout that has forms related to it
3. Add another textview below #2 and name it address
4. Add a lyout below #3 .
The layout 2 and 4 will have visibility gone in the first case
When the user taps on layout 1, or the first textview, make layout 2 visible and vice versa. Do the same with the second textview.
Hope that helps.!
I have had a similar problem, i want parts of my form to be hidden in sektions and created a class for this issue.
public class section extends LinearLayout{
public LinearLayout container;
public Button toggler;
public section(Context context, String section_name, String section_state) {
super(context);
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.flxsection, this);
container = (LinearLayout) this.findViewById(R.id.container);
container.setVisibility(section_state.equals("0") ? View.GONE:View.VISIBLE);
toggler = ((Button)this.findViewById(R.id.section_toggle));
toggler.setTag(section_state);
toggler.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
String tag = (String) v.getTag();
v.setTag(tag.equals("0") ? "1":"0");
if(tag.equals("0")){expand(container,false);}else{collapse(container,false);}
setImage(tag.equals("0"));
}
});
toggler.setText(" " + section_name);
setImage(section_state.equals("1"));
setTextSize();
}
public void setTextSize(){
toggler.setTextSize(GV.Style.TextSize);
}
public void setImage(boolean open){
int a = open ? R.drawable.minus_48_white: R.drawable.plus_48_white;
Drawable img = main.res.getDrawable(a);
final float scale = main.res.getDisplayMetrics().density;
int size = (int) (12 * scale + 0.5f);
img.setBounds(0,0,size,size);
toggler.setCompoundDrawables(img,null,null,null);
}
}
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="wrap_content"
android:background="#android:color/transparent"
android:focusable="false"
android:layout_marginLeft="4dip"
android:layout_marginRight="4dip"
android:orientation="vertical" >
<Button
android:id="#+id/section_toggle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dip"
android:layout_marginTop="4dip"
android:background="#drawable/section"
android:drawableLeft="#drawable/plus_48"
android:focusable="false"
android:gravity="left|center_vertical"
android:padding="6dip"
android:textAppearance="?android:attr/textAppearanceLargeInverse"
android:textSize="22dip" />
<LinearLayout
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:background="#android:color/transparent"
android:orientation="vertical" >
</LinearLayout>
Expand and collapse:
public static void expand(final View v,boolean quick) {
v.requestLayout();
v.measure(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
final int targtetHeight = v.getMeasuredHeight();
v.getLayoutParams().height = 0;
v.getLayoutParams().width = LayoutParams.FILL_PARENT;
v.setVisibility(View.VISIBLE);
if(quick){
v.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
v.requestLayout();
}else{
android.view.animation.Animation a = new android.view.animation.Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? LayoutParams.WRAP_CONTENT
: (int)(targtetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
int duration = (int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density);
if(duration> 500)duration=500;
a.setDuration(duration);
//(int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density)
v.startAnimation(a);
}
}
public static void collapse(final View v,boolean quick) {
v.requestLayout();
final int initialHeight = v.getMeasuredHeight();
if(quick){
v.setVisibility(View.GONE);
v.requestLayout();
}else{
android.view.animation.Animation a = new android.view.animation.Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if(interpolatedTime == 1){
v.setVisibility(View.GONE);
}else{
v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
v.requestLayout();
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
// 1dp/ms
int duration = (int)( initialHeight/ v.getContext().getResources().getDisplayMetrics().density);
if(duration> 500)duration=500;
a.setDuration(duration);
v.startAnimation(a);
}
}
If if create a form and need a section, i create a instance of this class and add the controls.
You might need to turn the hardware acceleration on in order to get the best performance
edit:
Usage is like:
section s = new section(context, section_name, section_state);
s.container.addView([your view 1]);
s.container.addView([your view 2]);
s.container.addView([your view 3]);
//...
form.addView(s);

Categories

Resources