Definitely Android tablet if affordable for a MUCH MUCH faster speed.
Android simulator drived me CRAZY this whole afternoon, especially when the project grows big and you have to debug and compile frequently.
Definitely Android tablet if affordable for a MUCH MUCH faster speed.
Android simulator drived me CRAZY this whole afternoon, especially when the project grows big and you have to debug and compile frequently.
If Android decides to recreate your Fragment later, it’s going to call the no-argument constructor of your fragment. So overloading the constructor is not a solution.
With that being said, the way to pass stuff to your Fragment so that they are available after a Fragment is recreated by Android is to pass a bundle to the setArguments
method.
So, for example, if we wanted to pass an integer to the fragment we would use something like:
public static MyFragment newInstance(int someInt) {
MyFragment myFragment = new MyFragment();
Bundle args = new Bundle();
args.putInt("someInt", someInt);
myFragment.setArguments(args);
return myFragment;
}
And later in the Fragment you can access that integer by using:
getArguments().getInt("someInt", 0);
This Bundle will be available even if the Fragment is somehow recreated by Android.
Also note: setArguments can only be called before the Fragment is attached to the Activity.
For example, if you want to change com.example.app
to my.awesome.game
, then:
Compact Empty Middle Packages
optionRefactor
Rename
Rename Package
instead of Rename Directorycom
in Android Studio, it might give a warning. In such case, selectRename Allbuild.gradle
– Usually app
or mobile
). Update the applicationId
to your new Package Name and Sync Gradle, if it hasn’t already been updated automatically:At 2014 Google I/O, Google announced a new visual language called Material Design. Material Design guides creation of user experiences that work well on different devices, with different input methods and on different platforms. Google is gradually implementing Material Design in their apps and products, and we can start playing with it, too.
One interesting new design pattern is the promoted action, implemented as a floating action button. This pattern exemplifies the underlying principles of Material Design and is a good place to start adapting existing applications to the new version of Android.
You can see from Google’s guidelines that there are many ways to apply this pattern incorrectly, as evidenced by the various “Don’ts” on that page. Today, I want to show you how to implement a floating action button without creating a “Don’t” yourself.
If you are just as excited as I am to get my hands dirty and create clean user interfaces with Google’s Material Design, you have probably already downloaded Android Studio 1.0 and Android Lollipop emulator images. If not, go ahead and do so now.
Our Criminal Intent project is a perfect fit for this tutorial. If you haven’t done so, grab your copy ofAndroid Programming: The Big Nerd Ranch Guide and work through Chapters 7-22. (If you’ve done this a long time ago and can’t locate your code, you can also get the solutions from our website).
In the Criminal Intent app, the “Add New Crime” button appears in the Action Bar. It’s a good candidate to be the promoted action, so we will update the app for Lollipop. This is what our final result will look like:
Before we work on the button, we need to remove the “Add New Crime” menu item, by creating the res/menu-v21/fragment_crime_list.xml
file:
<!-- res/menu-v21/fragment_crime_list.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_item_show_subtitle"
android:title="@string/show_subtitle"
android:showAsAction="never"/>
</menu>
Now it’s time to add the button. Since CrimeListFragment
is a subclass of ListFragment
, we didn’t have to define a layout for it. We’ll do this here, by creating fragment_crime_list.xml
in layout-v21
:
<!-- res/layout-v21/fragment_crime_list.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@android:layout/list_content"/>
<ImageButton
android:id="@+id/add_button"
android:layout_width="@dimen/round_button_diameter"
android:layout_height="@dimen/round_button_diameter"
android:layout_gravity="end|bottom"
android:layout_marginBottom="@dimen/add_button_margin"
android:layout_marginEnd="@dimen/add_button_margin"
android:src="@android:drawable/ic_input_add"/>
</FrameLayout>
We will use this layout for Lollipop and fall back to the super
implementation for previous versions (in CrimeListFragment.java
):
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
v = inflater.inflate(R.layout.fragment_crime_list, parent, false);
} else {
v = super.onCreateView(inflater, parent, savedInstanceState);
}
At the time of the original post Lollipop hadn’t come out yet. Because Android L was a preview release, things worked a bit differently.
Build.VERSION_CODES.L
did exist, but its value was set to 10000. The Android L emulator’sBuild.VERSION.SDK_INT
was 20. Thus we had to use codeKITKAT_WATCH
, even though it referred tov20
and notv21
. Now that Lollipop is out, we don’t have to play with numbers.
So far, the button doesn’t look like the floating action button we want. Let’s change the tint and background:
android:tint="@android:color/white"
android:background="@drawable/oval"
Better! But it’s still not floating. For that, we need to change its elevation:
android:elevation="@dimen/elevation_low"
Because the button is still rectangular, the elevated button drops a rectangular shadow. Fortunately, we can change the button’s outline and clip it (in CrimeListFragment.java
):
// CrimeListFragment.java - onCreateView()
View addButton = v.findViewById(R.id.add_button);
addButton.setOutlineProvider(new ViewOutlineProvider() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void getOutline(View view, Outline outline) {
int diameter = getResources().getDimensionPixelSize(R.dimen.diameter);
outline.setOval(0, 0, diameter, diameter);
}
});
addButton.setClipToOutline(true);
In Lollipop, the API changed a bit. Thanks to our commenters for pointing it out. Instead of
setOutline
, we now usesetOutlineProvider
.
The evolution of the button:
We’re almost done! We just need to do two things. First, we need to bring back the ripple effect. Second, we need to change the size of the shadow when the button is pressed.
To re-enable the ripple, we need to change the button’s background from a static shape to a rippleandroid:background="@drawable/oval_ripple"
and create the oval_ripple
drawable:
<!-- res/drawable/oval_ripple.xml -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="oval">
<solid android:color="?android:colorAccent"/>
</shape>
</item>
</ripple>
The last effect is to increase the size of the shadow, and we need to lift the button up after we push down on it. To make it happen, add one more property to the button: android:stateListAnimator="@anim/button_elevation"
and create the button_elevation
animation:
<!-- res/anim/button_elevation.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<objectAnimator
android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueFrom="@dimen/elevation_low"
android:valueTo="@dimen/elevation_high"
android:valueType="floatType"/>
</item>
<item>
<objectAnimator
android:propertyName="translationZ"
android:duration="@android:integer/config_shortAnimTime"
android:valueFrom="@dimen/elevation_high"
android:valueTo="@dimen/elevation_low"
android:valueType="floatType"/>
</item>
</selector>
These are the values in dimens.xml
:
<!-- res/values/dimens.xml -->
<dimen name="diameter">48dp</dimen>
<dimen name="elevation_low">1dp</dimen>
<dimen name="elevation_high">4dp</dimen>
<dimen name="add_button_margin">16dp</dimen>
Finally, the button needs to perform the action that used to be accessible via the Action Bar, so we add the OnClickListener
:
addButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNewCrime();
}
});
Here’s the zoomed in view of the finished result:
That’s it! With just a handful of new XML files and code, we kicked off the redesign of the Criminal Intent app and implemented a floating action button. There is a lot more to Material Design; read the guidelines, but keep in mind that they’re still being refined.
1. download system icons from google website http://www.google.com/design/spec/resources/sticker-sheets-icons.html#sticker-sheets-icons-components
2. all icons are in black, but there are svg files available, you can start to make change from there.
3. to have a transparent background, but @null in imagebutton background attribute.