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?
Related
I have a custom designed button (LinearLayout) that I want to reuse multiple times by just replacing a couple of attributes of the layout's nested views (icon and text).
I understand that using the <include> tag I can only override root view attributes.
I can sure do it programatically in java, but I wonder if there is a smart way to do this in XML.
Essentially, I want to be able to use something like <include> to reuse below shown complex layout and override only the following two nested attributes in two different nested views:
...
android:src="#drawable/google_icon"
...
android:text=" Google"
...
My (not yet) reusable layout:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_vertical_margin"
android:layout_marginBottom="#dimen/button_vertical_margin"
android:gravity="center_horizontal"
android:clickable="true"
android:background="#drawable/default_button_selector">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="-2dp"
android:background="#drawable/layout_border"
android:gravity="center">
<ImageView
android:layout_width="#dimen/button_icon_size"
android:layout_height="#dimen/button_icon_size"
android:layout_margin="#dimen/button_icon_margin"
android:src="#drawable/google_icon" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/layout_border"
android:gravity="center"
android:paddingLeft="#dimen/button_text_horizontal_padding"
android:paddingRight="#dimen/button_text_horizontal_padding">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_text_vertical_margin"
android:layout_marginBottom="#dimen/button_text_vertical_margin"
android:textSize="#dimen/button_text_size"
android:text="Continue with" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/button_text_vertical_margin"
android:layout_marginBottom="#dimen/button_text_vertical_margin"
android:text=" Google"
android:textSize="#dimen/button_text_size"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
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.
}
}
I try to align four checkboxes but one is not in the center of the other. If I shorten the text it fits but if its longer it looks like in the screenshot. The problem is it will be in different languages so the text size can be different. Also if I remove the scale it fits perfect but I need this bigger checkboxes
This is my code:
<CheckBox
android:id="#+id/cb1"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="23dp"
android:text="#string/unmounted"
android:textColor="#color/textBlack"
android:layout_below="#+id/abc"
android:layout_toEndOf="#+id/imageView6"
android:focusable="false"/>
<CheckBox
android:id="#+id/cb2"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/problem_not_working"
android:textColor="#color/textBlack"
android:layout_below="#+id/cb1"
android:layout_alignStart="#+id/cb1"
android:focusable="false"/>
<CheckBox
android:id="#+id/cb3"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/problem_cable_defective"
android:textColor="#color/textBlack"
android:layout_below="#+id/cb2"
android:layout_alignStart="#+id/cb2"
android:focusable="false"/>
<CheckBox
android:id="#+id/cb4"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/problem_cable_tie"
android:textColor="#color/textBlack"
android:layout_below="#+id/cb3"
android:layout_alignStart="#+id/cb3"
android:focusable="false"/>
Here is the exact solution for your problem, the thing which you are actually trying to achieve is the bigger checkbox view (corresponding to its text which is as big as the checkbox view, obviously) with proper alignment of all the views in the series, something like this:
Your desired UI.
But the thing you are doing wrong is that you are using the scaleX and scaleY attributes for achieving your desired UI that distorts your view as these two attributes scale the complete view i.e. the squared checkbox view with its text/label in the X and Y directions respectively (together with the text/label of the checkbox), so there is a dependency on the text as well (which is distorting your view).
So, the below code will solve your problem:
(In this I have taken the squared checkbox view as separate and beside it I have placed a textview in which I have written the text which corresponds to the text/label of that checkbox to complete the UI). Thereby using two views (i.e. the CheckBox and the TextView beside it) instead of using a single compound view (i.e. the CheckBox).
Note: In the solution given below, the CheckBox is a compound view but I haven't used it in the
same manner.
<?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">
<View
android:id="#+id/some_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="20dp"
android:layout_marginTop="23dp" />
<!--android:text="Unmounted"-->
<CheckBox
android:id="#+id/cb1"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="23dp"
android:layout_below="#+id/some_view"
android:layout_alignStart="#+id/some_view"
android:focusable="false" />
<TextView
android:id="#+id/tv_for_cb1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#id/cb1"
android:layout_alignTop="#+id/cb1"
android:layout_alignBottom="#+id/cb1"
android:layout_marginStart="40dp"
android:text="Unmounted"
android:textColor="#android:color/black"
android:textSize="24sp" />
<!--android:text="Problem Not Working"-->
<CheckBox
android:id="#+id/cb2"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="23dp"
android:layout_below="#+id/cb1"
android:layout_alignStart="#+id/cb1"
android:focusable="false"/>
<TextView
android:id="#+id/tv_for_cb2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#id/cb2"
android:layout_alignTop="#+id/cb2"
android:layout_alignBottom="#+id/cb2"
android:layout_marginStart="40dp"
android:text="Problem Not Working"
android:textColor="#android:color/black"
android:textSize="24sp" />
<!--android:text="Problem Cable Defective"-->
<CheckBox
android:id="#+id/cb3"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="23dp"
android:layout_below="#+id/cb2"
android:layout_alignStart="#+id/cb2"
android:focusable="false"/>
<TextView
android:id="#+id/tv_for_cb3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#id/cb3"
android:layout_alignTop="#+id/cb3"
android:layout_alignBottom="#+id/cb3"
android:layout_marginStart="40dp"
android:text="Problem Cable Defective"
android:textColor="#android:color/black"
android:textSize="24sp" />
<!--android:text="Problem Cable Tie"-->
<CheckBox
android:id="#+id/cb4"
android:scaleX="1.3"
android:scaleY="1.3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="23dp"
android:layout_below="#+id/cb3"
android:layout_alignStart="#+id/cb3"
android:focusable="false"/>
<TextView
android:id="#+id/tv_for_cb4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#id/cb4"
android:layout_alignTop="#+id/cb4"
android:layout_alignBottom="#+id/cb4"
android:layout_marginStart="40dp"
android:text="Problem Cable Tie"
android:textColor="#android:color/black"
android:textSize="24sp" />
</RelativeLayout>
And the other way out to your mentioned problem would be to create custom drawables for the checkbox and then handle them using a state list drawable as for the checkbox to be shown differently in different states as when it is unchecked, checked etc.
This link would help you if you are interested in doing it in this manner or way and would be great if you want to customize your checkbox's view.
Creating custom checkbox using selectors and shapes.
For further help in this context refer:
Android: How to change CheckBox size?
Here's my layout screenshot:
How can I arrange all these TextView for them to have a good format (heading being Taking responsibility (means being aware)..) alignment etc.
<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=".Menu"
android:background="#android:color/holo_blue_bright"
>
<TextView
android:text="*Follow safety guide for moving around the town and between towns."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView25"
android:gravity="left"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="51dp" />
<TextView
android:text="*Avoid crowds and do not participate actively in demonstrations even when it is related to programme work."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView25"
android:gravity="left"
android:layout_below="#+id/textView25"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="15dp" />
<TextView
android:text="*Avoid crowds and do not participate actively in demonstrations even when it is related to programme work."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView25"
android:gravity="left"
android:layout_marginBottom="23dp"
android:layout_above="#+id/textView25"
android:layout_toRightOf="#+id/textView25"
android:layout_toEndOf="#+id/textView25" />
<TextView
android:text="*keep this briefing pack in an accessible place, and the emergency numbers in your mobile phone memory"
android:layout_width="wrap_content"
android:gravity="bottom"
android:layout_height="wrap_content"
android:id="#+id/textView28"
android:layout_above="#+id/textView25"
android:layout_toRightOf="#+id/textView25"
android:layout_toEndOf="#+id/textView25"
android:layout_marginBottom="46dp" />
<TextView
android:gravity="center"
android:textColor="#000"
android:textSize="15dp"
android:text="Taking resposibility(means being aware)"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/textView22"
android:layout_marginTop="18dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="*Avoid moving around town by yourself and always make others aware of your location."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:id="#+id/textView25"
android:layout_marginTop="76dp"
android:layout_below="#+id/textView22"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:text="*Share any security information that might have implications for Ballloon Ventures to the Country Manager or pc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView24"
android:gravity="left"
android:layout_below="#+id/textView26"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="30dp" />
<TextView
android:text="*If using host home accommondation,check that it is secure.if it is not,tell the Programme Coordinator"
android:layout_width="wrap_content"
android:gravity="bottom"
android:layout_height="wrap_content"
android:id="#+id/textView28"
android:layout_marginTop="14dp"
android:layout_below="#+id/textView24"
android:layout_alignRight="#+id/textView25"
android:layout_alignEnd="#+id/textView25" />
<TextView
android:text="*Report all incidents to your Programmer Cordinator."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textView26"
android:gravity="left"
android:layout_below="#+id/textView25"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="55dp" />
</RelativeLayout>
Because if I drag one TextView it affecting all other TextView.
As #GabeSechan said, you need to learn what android:layout_xxx properties in RelativeLayout means.
When you moving a View in RelativeLayout via Layout Editor, you need to consider some of the following properties in your layout:
android:layout_above="#+id/textView25"
android:layout_below="#+id/textView24"
android:layout_toRightOf="#+id/textView25"
android:layout_toEndOf="#+id/textView25"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_above="#+id/textView25" means that you want the View above textView25 view.
android:layout_below="#+id/textView24" means that you want the View below textView25 View.
The following properties means that you want the view to the right side of TextView25 View:
android:layout_toRightOf="#+id/textView25"
android:layout_toEndOf="#+id/textView25"
The following properties means that you want the view to align with the left side of the parent layout:
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
If you want to edit views position in a RelativeLayout, please don't depends with drag and drop via Layout Editor. You better do it manually except you want to have a headache later. Use Layout Editor to view the design result.
Design with a paper or imagination first, then code it after that.
Try to learn it from:
Relative Layout
Constructing View Layouts
The best practice for doing that would be to open a splitview between your code and design views and then editing the code to place the text in the correct location, using attributes such as padding, margin, aligning, below, above, etc. refer to this guide for positioning stuff in relative layout and combine it with other formatting attributes such as margin and padding.
I'm trying to set my TextView to the left of an ImageButton, but I can't seems to find this option.
I was expecting to use something like android:layout_alignLeft, but this option is missing.
I've tried to google the issue, but couldn't find any relative results.
Without it my TextView overlaps the ImageButton and I want to avoid it.
UPDATE
The full xml code is too complex, but here is the important part of it:
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentLeft="true"
android:background="#color/white"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_toLeftOf="#+id/frameLayoutBalanceClosed">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/button_edit_nickname"
android:id="#+id/card_closed_control_editNickname" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/card_closed_description_nickname"
android:layout_margin="8dp" android:layout_gravity="left"/>
</FrameLayout>
I think what you need is a RelativeLayout. You can specify your TextView to the left of your ImageView with it's specifications. Your code would look something like this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/imagebutton1" />
<ImageButton
android:id="#+id/imagebutton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
The reason FrameLayout isn't working is because it's purpose is to overlay items on top of each other, which wouldn't work at all!
If that isn't what you're looking for, you could also use a TableLayout in which items are arranged in columns.