I'm developing a simple BMI calculator for android. I have input fields for lbs, feet, and inches. I want to give users the ability to switch from imperial units to metric, so I added a spinner widget with imperial and metric as options. If the user changes the spinner to metric, I want to be able to change the XML layout so that the input fields are kg and cm. What is the best way to change the XML layout when the user switches between metric and imperial?
I tried creating a new activity that loads the metric layout XML when the user switches to it, but it seems like a poor design to create a new activity just to switch units. I also tried simply using setContentLayout to set the layout to metric.xml if spinner has metric selected and imperial.xml if imperial is selected. This sort of works but the ads and spinner widgets are no longer configured after switching between the layouts. I am still new to android development so I am wondering what the best approach to this would be? I am simply trying to make a slight layout change when the user switches between the different unit options. Any tips appreciated.
Normally, I would put everything inside activity layout xml file and toggle based on the condition like this
<TextView
android:id="#+id/feet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"/>
<TextView
android:id="#+id/inch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"/>
And in your spinner adapter selection listener, you can toggle the view you want to show:
feet.setVisibility(View.VISIBLE)
You can use FrameLayout. It allow you to make to different layouts on each other (different views can be located on another views). For example:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#FFFFFF">
<RelativeLayout
android:id="#+id/digital_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginLeft="294dp"
android:layout_marginTop="64dp">
<Spinner
android:id="#+id/spinner101"
android:layout_width="135dp"
android:layout_height="wrap_content"
android:layout_below="#+id/checkBox100"
android:layout_toEndOf="#+id/textView100"
android:visibility="visible"/>
<TextView
android:id="#+id/textView102"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/spinner101"
android:text="Value pulse"
android:textSize="20dp"
android:visibility="visible"/>
<TextView
android:id="#+id/textView107"
android:layout_width="wrap_content"
android:layout_height="22dp"
android:layout_alignStart="#+id/textView106"
android:layout_below="#+id/textView103"
android:gravity="center"
android:text="11%"
android:visibility="visible"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/analog_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<EditText
android:id="#+id/editText3"
android:layout_width="136dp"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/spinner2"
android:layout_below="#+id/checkBox3"
android:ems="10"
android:hint="Constant"
android:inputType="textPersonName"
android:textSize="15dp"
android:visibility="invisible" />
<Button
android:id="#+id/button6"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignParentStart="true"
android:layout_below="#+id/checkBox9"
android:layout_marginLeft="20dp"
android:onClick="onResetClick"
android:text="Reset" />
<View
android:id="#+id/delitel1"
android:layout_width="234dp"
android:layout_height="2dp"
android:layout_alignStart="#+id/textView7"
android:layout_below="#+id/button6"
android:layout_marginTop="10dp"
android:background="#004f9b" />
<TextView
android:id="#+id/textView14"
android:layout_width="135dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/delitel1"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="Language:"
android:textSize="20dp"
android:visibility="invisible" />
</RelativeLayout>
So, you need to give different id to each RelativeLayouts. Here there are android:id="#+id/digital_layout" and android:id="#+id/analog_layout".
And in code need to write handler for your spinner:
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0:
digital_layout.setVisibility(View.INVISIBLE);
analog_layout.setVisibility(View.VISIBLE);
break;
case 1:
digital_layout.setVisibility(View.VISIBLE);
analog_layout.setVisibility(View.INVISIBLE);
break;
etc.
}
}
Related
I am making an app similar in design to a Reddit/YouTube/Yahoo News app, it uses the API's to gather information on recent posts.
When you start the app, it displays all the recent posts exactly like this:
http://wpuploads.appadvice.com/wp-content/uploads/2014/07/screen1136x1136-68-576x1024.jpeg
The goal is to make all posts conform to a match_parent width and wrap_content height (max 300 dp height) and - just like the picture linked above - make all the posts conform to one look; Title on the top, body/picture in the middle and number of comments underneath.
Let's say my common View layout is something like this:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="#ffffff"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lesson 1"
android:textAllCaps="false"
android:textColor="#8c8c8c"
android:textSize="40dp"
android:gravity="center_horizontal"/>
<ImageButton
android:id="#+id/imageButton1"
android:background="#drawable/lesson1"
android:layout_width="250dp"
android:layout_height="150dp"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="10 Comments"
android:textColor="#000000"/>
</LinearLayout>
I want to replicate this Layout style (Text, Image, Text) every time there is a new post and add it to the existing XML. How would I do this?
You would use a LayoutInflater to inflate the xml file into a View. Then you would add that view to the layout wherever you want it.
Revised Question
When one looks online in tutorials, or by Google IO presentations, there are always just 2 kinds of UI customizations that one can do (but there are several implementations of doing each type). These customizations are:
Creating a custom view that is a composite of existing views, or your own
Creating a custom layout that is your own
However, what if I wanted to create a hybrid of these two? Specifically a Custom View that allow child views to be laid out how I define? There is nothing that I have found online (no tutorials, no videos) or even anything saying if this is even feasible.
Idea
Here is the Contacts App that has something very similar to what I want to do. You notice that every list item has a very similar layout. Nothing special here. I can create composite custom view with styleables to set the primary and secondary text, and the main and action icons.
However, my secret sauce comes with the idea of changing the primary text (the blacked-out region) to some other view in XML! This view could be a TextView, RatingBar, ProgressBar, VideoView, SurfaceView, etc...
Examples
TextView
Here is an example of using my custom view that takes in a developer-defined TextView.
<com.example.customview.BaseViewLayout
...
custom:imageMainIcon="..."
custom:imageActionIcon="..."
custom:secondaryText="Home">
<TextView
...
android:text="User-defined TextView"
... />
</com.example.customview.BaseViewLayout>
VideoView
Here is an example of using my same custom view that takes in a developer-defined VideoView.
<com.example.customview.BaseViewLayout
...
custom:imageMainIcon="..."
custom:imageActionIcon="..."
custom:secondaryText="Home">
<VideoView
... />
</com.example.customview.BaseViewLayout>
Code
BaseCustomLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/detail_list_item"
android:layout_width="450dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:minHeight="72dp"
android:background="#color/material_blue_grey_800" >
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
android:src="#drawable/ic_not_available_white"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="#+id/imageView" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="72dp"
android:layout_marginStart="72dp"
android:layout_marginRight="72dp"
android:layout_marginEnd="72dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:layout_toRightOf="#+id/imageView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<ViewStub
android:layout_height="20dp"
android:layout_width="wrap_content"
android:id="#+id/view_stub_main_view"
android:inflatedId="#+id/inflated_main_view" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="20dp"
android:paddingTop="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="16dp"
android:text="Item Type"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="16dp"
android:textStyle="bold"
android:text=" ยท "/>
<TextView
android:layout_width="wrap_content"
android:layout_height="16dp"
android:text="Extra"/>
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:src="#drawable/ic_not_available_white"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:padding="8dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:id="#+id/imageView2" />
</RelativeLayout>
So, how does a person go about developing a custom view like this?
Xml Code:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/trip2"
android:orientation="vertical">
<com.cengalabs.flatui.views.FlatTextView
android:id="#+id/Rpickdtetx"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Return Pick Up Date"
/>
<com.cengalabs.flatui.views.FlatEditText
android:id="#+id/Rpickdte"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:maxLines="1"
android:textSize="15dp" />
</LinearLayout>
</RelativeLayout>
<!--Return Pick up time-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.cengalabs.flatui.views.FlatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Return Pick Up Time"
android:textSize="15dp"
flatui:fl_theme="#array/grass"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" />
<com.cengalabs.flatui.views.FlatEditText
android:id="#+id/Rpicktme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:maxLines="1"
android:gravity="center_vertical"
android:hint="Pick-Up Time"
android:includeFontPadding="true"
android:drawableLeft="#drawable/time"
flatui:fl_fieldStyle="fl_box"
/>
</LinearLayout>
</RelativeLayout>
.java code
Triptype.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.triptype1:
view.findViewById(R.id.trip2).setVisibility(View.INVISIBLE);
view.findViewById(R.id.trip21).setVisibility(View.INVISIBLE);
/* view.findViewById(R.id.Rpickdte).setVisibility(View.INVISIBLE);
view.findViewById(R.id.Rpickdtetx).setVisibility(View.INVISIBLE);*/
break;
case R.id.triptype2:
ReturnTrip(view);
break;
}
}
});
I am newbie to android,I am using radio button on toggling,have to add some text boxes(above xml code of text boxes),My query making visible/invisible text box even though i wrap_content, can see a empty space.Can anyone help me how to resolve that.
view.findViewById(R.id.trip2).setVisibility(View.GONE);
view.findViewById(R.id.trip21).setVisibility(View.GONE);
/* view.findViewById(R.id.Rpickdte).setVisibility(View.GONE);
view.findViewById(R.id.Rpickdtetx).setVisibility(View.GONE);*/
break;
set them to "Gone" instead of "invisible" will help to retain space
Try to use View.GONE instead of View.INVISIBLE.
The documentation says:
View.GONE: This view is invisible, and it doesn't take any space for layout purposes.
View.INVISIBLE: This view is invisible, but it still takes up space for layout purposes.
If you want to know more, you can look at this question.
I'm new to Android development and I'm trying to achieve a layout for my app that is capable of handling different screen resolutions/ratios.
I've been reading a lot of the documentation and questions on this site to try to understand the basics and concepts.
First I went through:
developer.android.com/guide/practices/screens_support.html
And questions like:
stackoverflow.com/questions/6403619/how-to-support-all-the-different-resolutions-of-android-products
I've got a pretty basic idea on how to handle things out. But still, its pretty difficult for a starter to get going, and I found myself stucked trying to achieve the solution I came up with.
I designed my app to a target resolution of 480x800, and set it up to always show in portrait mode.
This is how it looks like and how I understand it should work (I used Waldo for the sake of example haha):
(sorry for the link, I need 10 rep to post images)
http://i.imgur.com/KXTAXir.jpg
My root Layout is a LinearLayout, wich contains 3 other Layouts being A and C set up to a weight of 0.8 while B is at 8.4. This is all fine, but the contents of B are set up to DP units at the moment just to be able to test.
B consists of a frame Layout who has 3 other Layouts inside, where 2 of them are working fine, and shown only when needed. The problem is that I need B to be able to adapt based on the contents of it first child: a LinearLayout wich contains 2 ImageView and 1 ProgressBar. I need that those ImageView always keep their ratio.
Here is an example of how it should work:
http://i.imgur.com/cH7fUze.jpg
Imagine those 4 are real screens, wich vary in ratio and size. So my app should only adapt B (from my first image) to keep the images original ratio.
Here is the layout code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/darkgray"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.8"
android:background="#666666" >
<TextView
android:id="#+id/level_text_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="LEVEL"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="#+id/level_text_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="SCORE"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="#+id/level_text_clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="01:59"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="8.4" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="200dp"
android:adjustViewBounds="true" />
<ProgressBar
android:id="#+id/progressBar1"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="1000"
android:progress="0" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:adjustViewBounds="true" />
</LinearLayout>
<RelativeLayout
android:id="#+id/pauseMask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:visibility="gone" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/gameoverMask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:visibility="gone" >
</RelativeLayout>
</FrameLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.8"
android:background="#666666" >
<TextView
android:id="#+id/level_text_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="0/0"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Button"
android:onClick="useHint" />
<Button
android:id="#+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/button1"
android:layout_centerVertical="true"
android:text="Button"
android:onClick="toggleSound" />
<Button
android:id="#+id/button3"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/button2"
android:layout_centerVertical="true"
android:text="Button"
android:onClick="togglePause" />
</RelativeLayout>
The last thing that stays unclear to me is how to handle the text and button sizes. Should I set them in DPs? How do I get them to scale accordingly like it can be seen on the bottom of my second picture.
Thank you for your help, I also want this to serve as an example to others that are having trouble to understand how to handle this kind of scenarios.
I'm not sure, if I got your question right.
However, you can specify different layouts for different screen sizes and orientations, as described here: http://developer.android.com/guide/practices/screens_support.html
Just give the respective suffix in the name of your layout XML file.
I ended up creating a custom View for my images. The view calculates the space thats left on its parent, scales the images manually and then resizes itself to the same size of the resulting image.
To resize the progress bar to have the same width as the images, I used a custom listener that gets triggered when my custom views get resized. Then I resize the progressbar to match their width.
With this I achieved what I wanted, a layout that will work perfectly in all screen sizes.
I am trying to modify the design of Spinner widget. I can change the background, but I can't find a way to change the arrow icon on the right side. Is there a way to do it?
Thanks!
The whole thing is a single 9 patch png image. I've modified the entire look of spinners before by replacing the images. See this page: http://androiddrawableexplorer.appspot.com/
Specifically look at btn_dropdown_normal.9, btn_dropdown_pressed.9, btn_dropdown_selected.9 and btn_dropdown_disabled.9
You just need to provide your own versions of those images.
Also, you can place your "spinner bar" layout in a FrameLayout, together with the real spinner but set to invisible:
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="32dip"
>
<Spinner
android:id="#+id/theSpinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="32dip"
android:background="#drawable/my_background"
android:padding="6dip"
android:clickable="true"
android:onClick="spinnerBarReplacementClicked"
>
<ImageView
android:id="#+id/replacementSelectImg"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="#drawable/my_drawable"
/>
<TextView
android:id="#+id/replacementSelectText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="4dip"
android:layout_toLeftOf="#id/replacementSelectImg"
android:textColor="#000000"
android:textSize="14sp"
android:ellipsize="marquee"
android:singleLine="true"
/>
</RelativeLayout>
</FrameLayout>
and pass the clicks from your layout to the real spinner
private Spinner mSpinner;
mSpinner = (Spinner) findViewById(R.id.theSpinner);
public void spinnerBarReplacementClicked(View pV){
mSpinner.performClick();
}