Problem
The Android SDK classes refer to pre-defined layouts using resource IDs.
In my example, I am creating a custom Preference
class and want to create a custom layout (including custom widgets) for that preference type. This all works fine, for example I can have a TextView
displaying the preference title specified with android:title
in XML (which is no custom attribute).
The problem is that I want the style of my custom layout to conform with the style used by the standard Android Preference
classes. This includes for example the text size and style. I could simply try it out to find the matching style but I suspect that the style Android uses is general so that it would adapt with the general style of the app.
Approaches
I looked into the Preference
class in the SDK and found that for the title it does the following:
TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title)
This hints that all the style is defined in a layout file. Now my question is: how to find this layout file? I wonder whether the resource id used here is enough, it looks so general that it might be even used for multiple purposes (that is, titles in other places than the Preference
class). Is that the case?
To find the layout file, I looked for example in <android-sdk>/platforms/android-24/data/res/layout
and it indeed contains some resources with names including "preference".
For example, the file preference_category.xml
looks as follows:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/listSeparatorTextViewStyle"
android:id="@+android:id/title"
/>
Here a title
id is defined. Is that an id the above com.android.internal.R.id.title
would refer to?
I can find further relevant layout files, where preference_child.xml
looks quite promising:
<TextView android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
But still I would have to guess whether it is the file I am looking for. Thus the question is: How do I find the right layout file? There is not much documentation in the XML files. How does one in general find the layout files used at different places in the Android framework?
A related question (Where can I find default AlertDialog layout xml file? ) has an answer indicating that I looked at the right directory in the SDK. However, the answer does not tell how in general one proceeds to find the layout one is looking for.
The concrete case with a custom Preference
Relevant post: Android: Creating custom preference
In the linked answer the author suggests (by the given code) to create an own title TextView
. I am wondering whether one can instead reuse the layout given by Android, keeping the TextView
s for title and summary and just adding the own widget at the place noted in the XML, with id @android:id/widget_frame
. Would that be possible without copying it and adapting it in a new layout file? The full file preference_child.xml
from the Android SDK looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2006 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout for a visually child-like Preference in a PreferenceActivity. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingStart="16dip"
android:paddingEnd="?android:attr/scrollbarSize">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="@dimen/preference_widget_width"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_weight="1">
<TextView android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
<TextView android:id="@+android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="4" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="@dimen/preference_widget_width"
android:gravity="center"
android:orientation="vertical" />
</LinearLayout>