PK creative Spring Festival, I am participating in the “Spring Festival creative submission contest”, please see: Spring Festival creative submission Contest
In order to celebrate the New Year, we are going to produce a series of material design style components using the series. This is the first article to try the water 😊
Let’s take a look at today’s results:
MaterialButton MaterialButtonToggleGroup |
Chip ChipGroup |
ChipDrawable ChipsView ChipsInput |
---|---|---|
⚠️: this series of official documents and their own understanding of the preparation, not involved in the source part, all use!
The environment
- system: macOS
- Android studio: 4.1.3
- Gradle: gradle – 6.5 – bin. Zip
- Project gradle: 4.1.3
- Kotilin: 1.5.0
- ViewBinding: true
- Material: 1.4.0
- Appcompat: 1.4.0
Material Environment Configuration
Set the theme
First you need to change the theme to material style
// Use AppCompat style without ActionBar
<style name="MyTheme" parent="Theme.AppCompat.Light.NoActionBar">
// Material theme corresponding to AppCompat style without ActionBar
<style name="MyTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
// Current Material Style theme (with ActionBar)
<style name="MyTheme" parent="Theme.MaterialComponents.Light">
Copy the code
Subject Reference link
Configure in XML
Not configured by default, no material style component changes are visible
Select the corresponding theme, and the Material style will now be displayed
Use the Material theme control in the existing AppCompat theme
You can see in theAppCompat
Use in topicsmaterial
The theme space will crash directly, they are incompatible…
If you set theme to AppCompat in
Will need to usematerial
The component’sactivity
Set tomaterial
Theme!
Tips: Material theme is compatible with AppCompat theme, but AppCompat theme is not compatible with Material theme
Let’s get to the point!
MaterialButton
The original button:
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MD button" />
Copy the code
MaterialButton displayed on one side of the text:
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Icon on the left"
app:icon="@drawable/ic_emoji_02"
app:iconGravity="textStart"
app:iconPadding="10dp"
app:iconSize="40dp" />
Copy the code
- App :iconPadding=”dp” Distance between icon and text
- App :iconSize= Size of the “dp” icon
- App :iconGravity= “” icon mode
Other effects:
parameter | instructions | The effect |
---|---|---|
On the left side of the | app:iconGravity=”textStart” | |
On the right side | app:iconGravity=”textEnd” | |
upper | app:iconGravity=”textTop” | |
It can be seen that the icon is on one side of the text, but why is the picture black? |
My original image looked like this:
Here is the tone and tone mode to set the icon again:
If normal display is required, it can be set as follows:
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
.
app:iconTint="@color/white"
app:iconTintMode="multiply" />
Copy the code
- App :iconTintMode=”” Set tone mode
- App :iconTint= “” Set tone color
What is tonal color? Like this:
<com.google.android.material.button.MaterialButton
.
app:iconTint="@color/red"
app:iconTintMode="multiply" />
Copy the code
<com.google.android.material.button.MaterialButton
.
app:iconTint="@color/red"
# app:iconTintMode="multiply"
# app:iconTintMode="add"
# app:iconTintMode="src_over"
/>
Copy the code
Display of other color modes:
multiply | add | src_over |
---|---|---|
The background color |
<com.google.android.material.button.MaterialButton
.
android:backgroundTint="@color/red"
android:backgroundTintMode="add" />
Copy the code
The background tone is similar to the diagram above, so don’t do much styling
Water ripples [app: rippleColor]
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Water ripple color"
app:rippleColor="@color/red" />
Copy the code
Stroke rounded corners
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="The stroke (stroke)." "
android:textAllCaps="false"
app:cornerRadius="30dp"
app:strokeColor="@color/red"
app:strokeWidth="1dp" />
Copy the code
Common styles
Text style:
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text Style"
android:textAllCaps="false"
app:icon="@drawable/ic_emoji_08" />
Copy the code
Effect:
Built-in Stroke style:
<com.google.android.material.button.MaterialButton
style="? attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Own stroke style"
android:textAllCaps="false" />
Copy the code
Custom attributes [app:shapeAppearance]
If you need to customize a diamond edge, you can do this:You can refer toThe officialTo understand:
Summary of common properties of materialButton:
parameter | instructions |
---|---|
app:icon | icon |
app:iconPadding | Distance between icon and text |
app:iconSize | Icon size |
app:iconGravity | Pattern of ICONS |
app:iconTint | Color of icon |
app:iconTintMode | Color mode for an icon |
app:cornerRadius | Button with rounded corners |
app:strokeColor | Button outline color |
app:strokeWidth | Outline size of the button |
app:rippleColor | Water ripple color |
android:backgroundTint | The background color |
android:backgroundTintMode | Background tone mode |
@style/Widget.MaterialComponents.Button.TextButton | Writing style |
? attr/materialButtonOutlinedStyle | Comes with stroke style |
app:shapeAppearance | Custom properties (use with cornerFamily,cornerSize) |
cornerFamily | Trimming mode |
cornerSize | Trimming the size |
View more detailed parameters
MaterialButtonToggleGroup
Text style:
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/materialButtonGroup1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:checkedButton="@+id/bt2"
app:singleSelection="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/bt1"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:text="Dark mode"
.
/>
<com.google.android.material.button.MaterialButton
android:id="@+id/bt2"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:text="Light color mode"
. />
<com.google.android.material.button.MaterialButton
android:id="@+id/bt3"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:text="Follow system"
. />
</com.google.android.material.button.MaterialButtonToggleGroup>
Copy the code
Warm prompt: MaterialButtonToggleGroup inherited from LinearLayout
MaterialButtonToggleGroup parameter is introduced:
- Android: Orientation Settings
- App :singleSelection is a single option
- App :checkedButton is checked by default
Take a look at the results:
In order to prevent off screen, often using MaterialButtonToggleGroup, add a HorizontalScrollView, I like to give him to avoid beyond the screen
For example:
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/materialButtonGroup2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/bt4"
style="? attr/materialButtonOutlinedStyle"
android:text="Chinese" />
<com.google.android.material.button.MaterialButton
android:id="@+id/bt5"
style="? attr/materialButtonOutlinedStyle"
android:text="Mathematics" />
<com.google.android.material.button.MaterialButton
android:id="@+id/bt6"
style="? attr/materialButtonOutlinedStyle"
android:text="English"
android:textAllCaps="false" />
</com.google.android.material.button.MaterialButtonToggleGroup>
</HorizontalScrollView>
Copy the code
Of course, you can also add content via dynamic code:
val materialButtonList = listOf(
MaterialButton(
this.null,
R.attr.materialButtonOutlinedStyle // Set the style dynamically
).apply { text = "History" },
MaterialButton(
this.null,
R.attr.materialButtonOutlinedStyle // Set the style dynamically
).apply { text = "Chemistry" },
MaterialButton(
this.null,
R.attr.materialButtonOutlinedStyle // Set the style dynamically
).apply { text = "Music" },
MaterialButton(
this.null,
R.attr.materialButtonOutlinedStyle // Set the style dynamically
).apply { text = "Fine arts"},)// Dynamic add
materialButtonList.forEach {
binding.materialButtonGroup2.addView(it)
}
Copy the code
Take a look at the results:
We use the switching state hereSwitchMaterial
, running towards the principle of craftsman spirit, this first do not talk, will be talked about later!
The logic here should be clear once you read it
First listen to the state of the switch, through his state to determine whether the vertical | level, doing corresponding things
Here takeTrue is a small extension I wrote, non-0 and true
fun Boolean.takeTrue(other: Int = 1) =
if (!this) {
0
} else {
other
}
Copy the code
Chip
The simplest chip:
<com.google.android.material.chip.Chip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="The simplest chip" />
Copy the code
Chip has some properties that are common to the materialButton, which are directly introduced here!
<com.google.android.material.chip.Chip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Left picture"
android:checkable=""
android:checked=""
app:chipIconEnabled=""
app:checkedIcon=""
app:closeIcon=""
app:checkedIconEnabled=""
app:closeIcon=""
app:closeIconEnabled=""
app:chipIcon="@drawable/ic_emoji_01" />
Copy the code
parameter | type | instructions |
---|---|---|
android:checkable | Boolean | True activates the chip, which is false like a button |
android:checked | Boolean | Is it selected by default? |
— | — | — |
app:chipIcon | drawable | Icon (default on text side) |
app:chipIconEnabled | boolean | App: Whether chipIcon is active |
— | — | — |
app:checkedIcon | drawable | Click the button on the left (it will overwrite chipIcon) |
app:checkedIconEnabled | Boolean | App :checkedIcon active (default false) |
— | — | — |
app:closeIcon | drawable | The right button |
app:closeIconEnabled | Boolean | App: Whether the closeIcon button is active |
— | — | — |
app:chipBackgroundColor | color | The background color |
app:chipStrokeColor | color | Stroke color |
app:chipStrokeWidth | dp | Stroke width |
app:chipCornerRadius | dp | Rounded corners |
app:rippleColor | color | Water ripple color |
android:elevation | dp | Shadow color |
app:shapeAppearance | style | Custom properties (requires a cornerFamily) |
cornerFamily | enum | Custom cut edge style (not available alone) |
cornerSize | Custom cut edge size (invalid alone) |
Effect:
instructions | The effect |
---|---|
Some operations on icon | |
Click on the shadow |
ChipGroup
multi-select
ChipGroup inherits from FlowLayout
Let’s start with the simplest use:
<com.google.android.material.chip.ChipGroup
android:id="@+id/chipGroup1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:checkedChip="@id/chipPython"
app:chipSpacingVertical="5dp"
app:chipSpacingHorizontal="@dimen/dp_40">
<com.google.android.material.chip.Chip
.
android:text="java" />
<com.google.android.material.chip.Chip
.
android:text="kotlin" />
<com.google.android.material.chip.Chip
.
android:text="c" />
<com.google.android.material.chip.Chip
.
android:text="dart" />
<com.google.android.material.chip.Chip
.
android:text="C#" />
<com.google.android.material.chip.Chip
.
android:text="python" />
<com.google.android.material.chip.Chip
.
android:text="JS" />
</com.google.android.material.chip.ChipGroup>
Copy the code
- App :checkedChip is selected by default
- App: chipSpacingHorizontal horizontal distance
- App :chipSpacingVertical Vertical spacing
Take a look at the renderings:
ChipGroup# setOnCheckedChangeListener click
Note that this code is invalid! It can only be used in radio mode.
Register a callback to be invoked when the checked chip changes in this group. This callback is only invoked in single selection mode. Register a callback to be invoked when the chips checked in this group change. This callback is invoked only in single selection mode. (Baidu Translation)
If you want to force a click, you can do this:
// A bully can bend his bow
binding.chipGroup1.forEach { childView ->
if (childView is Chip) {
// Click listen
childView.click {
"${childView.text}-${childView.isChecked}" toast this
}
// Close the listener
childView.setOnCloseIconClickListener {
}
}
}
Copy the code
The principle is to loop through each chip in the chipGroup and add click events.
The radio
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.chip.ChipGroup
android:id="@+id/chipGroup2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:checkedChip="@+id/chipChinese"
app:singleLine="true"
app:singleSelection="true">
<com.google.android.material.chip.Chip
android:id="@+id/chipChinese"
style="@style/Widget.MaterialComponents.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Chinese" />
<com.google.android.material.chip.Chip
style="@style/Widget.MaterialComponents.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mathematics" />
<com.google.android.material.chip.Chip
style="@style/Widget.MaterialComponents.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="English" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
Copy the code
ChipGroup parameters:
- App :singleLine=”true” Set one line
- App: singleSelection = “true” radio
Of course, you can also add views dynamically, for example:
Take a look at the renderings:
ChipGroup parameters:
parameter | type | instructions | default |
---|---|---|---|
app:singleLine | Boolean | Whether to keep one line | false |
app:singleSelection | Boolean | Whether or not the radio | false |
app:checkedChip | id | Selected by default | |
app:chipSpacingHorizontal | dp | Horizontal spacing | |
app:chipSpacingVertical | dp | The vertical distance between | |
chipGroup#checkedChipIds | int[] | Gets the currently selected view collection | |
chipGroup#setOnCheckedChangeListener | (ChipGroup,checkedId) | Click Select (for Settings onlyApp: singleSelection = “true“The use of) | |
chipGroup#setOnHierarchyChangeListener | onChildViewAdded(parent: View? , child: View) onChildViewRemoved(parent: View? , child: View) |
Add and remove listeners |
View more Properties
Summary of use of style:
@ style/Widget MaterialComponents. Chip. The Action by default
@style/Widget.MaterialComponents.Chip.Entry | @style/@style/Widget.MyApp.Chip.Choice | @style/Widget.MaterialComponents.Chip.Filter |
---|---|---|
By default, the right delete button will be selected | Selection will leave color | When used in chipGroup, the check icon appears on the left |
If you want to have the selected icon and customize the color you selected, you can do this:
You can customize a selector. When you select a state, you can customize your color
ChipDrawable
ChipDrawable is often used in conjunction with editTextView, for example
xml:
<androidx.appcompat.widget.AppCompatTextView
.
android:text="ChipDrawable and Edit:" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Please enter 4 digits" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btPrintEdit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click on my output." />
Copy the code
ChipEditActivity:
// You can customize the length..
val tempLength = 4
binding.edit.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence? , start:Int, count: Int, after: Int){}override fun onTextChanged(
charSequence: CharSequence,
start: Int,
before: Int,
count: Int
){}override fun afterTextChanged(editable: Editable) {
/ / if
if (editable.length % tempLength == 0 && editable.isNotEmpty()) {
val chip: ChipDrawable =
ChipDrawable.createFromResource(this@ChipEditActivity, R.xml.item_chip)
chip.text = editable.subSequence(editable.length - tempLength, editable.length)
chip.setBounds(0.0, chip.intrinsicWidth, chip.intrinsicHeight)
val span = ImageSpan(chip)
editable.setSpan(
span,
editable.length - tempLength,
editable.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
})
Copy the code
R.xml.item_chip:
<chip xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:textAppearance="@style/ChipTextAppearance"
app:chipBackgroundColor="@color/cccccc"
app:chipIcon="@drawable/ic_emoji_05"
app:closeIconEnabled="false"
app:closeIconTint="@android:color/white"/>
Copy the code
To be honest, I feel this flaw is huge because it can’t click and I think it’s just an “effect”.. Still to develop
Take a look at the results:
For other details, please download the code to view..
ChipsInput
ChipsInput is an official address for chips components
However, it has not been maintained for many years, and it is more or less buggy to use
So I imported his Module into my project, corrected his bugs, and learned his code ideas
Usage Scenarios:
- The search box
- Some scenario-specific input fields
Use:
<com.pchmn.materialchips.ChipsInput
android:id="@+id/chips_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hint="Drop down input box [search em small icon by typing 'e']"
app:maxRows="3" />
Copy the code
Explore by yourself:
- app:chip_labelColor=”@color/black”
- app:chip_hasAvatarIcon=”true”
- app:chip_backgroundColor=”@color/black”
- app:chip_deletable=”false”
- app:hintColor=”@color/black”
- app:textColor=”@color/black”
- app:chip_deleteIconColor=”@color/teal_200″
- app:chip_detailed_textColor=”@color/teal_200″
- app:chip_detailed_backgroundColor=”@color/teal_200″
- app:chip_detailed_deleteIconColor=”@color/teal_200″
- app:filterable_list_backgroundColor=”@color/teal_200″
- app:filterable_list_textColor=”@color/teal_200″
Let’s look at dynamic code:Take a look at the results:
As you can see, only em1-EM9 is defined here, so that’s all you can search for.
There are other types of listener, such as input listener:
binding.chipsInput.addChipsListener(object : ChipsInput.ChipsListener {
override fun onChipAdded(chip: ChipInterface, newSize: Int) {
Log.e(TAG, "chip added, $newSize")}override fun onChipRemoved(chip: ChipInterface? , newSize:Int) {
Log.e(TAG, "chip removed, $newSize")}override fun onTextChanged(text: CharSequence?). {
// Input listener
Log.e(TAG, "chip text changed: " + text.toString())
}
})
Copy the code
Other details please download the code to view!
ChipsView
ChipsView is also an open source source written by foreigners gradually original address, this is also for a long time not to maintain, or use v7 package to write, there are some small bugs, I still import his module into my project to change, easy to use!
ChipsView I made a linkage effect with chipGroup, for example:
A little bit more code, here only look at the effect, specific details please download the code to view!
The complete code
Original is not easy, your praise is the biggest support for me!