“PK creative Spring Festival, I am participating in the” Spring Festival Creative submission contest “, please see: Spring Festival Creative Submission Contest”
Without further ado, let’s go to the picture above
- As can be seen from the figure, it is divided into
Up and down
Two parts. The first part is traditionSpring Festival couplets and the word "fu"
, is for everyoneNew Year greeting
The next part isThe main
Function module, includingThe amount of red envelopes, lucky New Year cards and yes or no
. - using
Kotlin
Language writing, involving the technology are:ConstraintLayout
,Drawable
,The custom View
,Android animation
,Viewpager2
,Font Settings
andUse of sensors
.
Sources.
- The source of this idea is mainly old people, they will give it to their nieces and nephews
Send a red envelope
Hahaha, this time the amount can be their ownShake out
, has theInteraction and randomness
More fun, forAdd fun to the New Year
! - The New Year
Lucky sign
It’s for everyoneblessing
! - You’re going to have a lot of scenarios that are going to happen
Choose difficult
, soIs and is not
This module isSolve such problems
Add the! - New Year is
move
Ah, just traditionalThe head
You can use your cell phoneshake
To simulate theThe effect
Move your wristKill two birds with one stone
What a good idea! The android mobile phone
Friends canDownloading the Installation packageexperience
A handful, I amCan't stop
!
Here we go
- First of all, this layout looks pretty simple, right,
LinearLayout
Set the directionvertical
I’m using one in the middleLinearLayout
Set the directionhorizontal
.- But that raises a question,
Nested layout
So that’s why I use it. RightConstraintLayout
To implement the reason, as shown below, only usedA layer of
.
- But that raises a question,
ConstraintLayout use
- Long-winded two sentences, some small partners can be used, you can refer to
- in
ConstraintLayout
In the controlEither way
allSelect at least one constraint
Otherwise, the control will be inThe top left corner is placed
. top
Refers to the topbottom
Refers to the bottomstart
Refers to the leftend
Point to the right. Here’s an example
- in
<com.android.springfestival.view.SpringTextView android:id="@+id/top" android:layout_width="wrap_content" android:layout_height="? actionBarSize" android:background="@drawable/shape_red_solid" android:gravity="center" android:paddingLeft="10dp" Android :paddingRight="10dp" Android :text=" 12sp "Android :textSize="24sp" Android :textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />Copy the code
- This is a
Horizontal batch
The text can be seen on itAt the top of the
andTop of parent layout constraints
.On the left
andThe left side of the parent layout is constrained
.On the right
andThe right side of the parent layout is constrained
.The horizontal center
Need to bePut constraints on the left and the right
If not, you want the control inWhich way to start
, let itConstrain to that direction
, such asHorizontal batch is placed at the top
.
- And what I want to do is let
The upper part accounts for 70 percent
.The lower part is thirty percent
- add
Guideline control
.Up and down
Set up theFor horizontal orientation
And want toAbout points
Instead ofvertical
Can. layout_constraintGuide_percent
Property to setOr on the left
How much? The range of values is0 to 1
.
- add
<androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" Android: layout_height = "wrap_content" android: orientation = "horizontal" app: layout_constraintGuide_percent = "0.7" / >Copy the code
- In the middle of the
couplets
andblessing
Word, I intend toblessing
Word ofThirty percent
And the restTen percent each
, so the width and height of the controls are set to 0dp, that is, to fill the remaining spaceThe transverse
theThe weight
.1:3:1
.- Lateral weight
app:layout_constraintHorizontal_weight
- Because the word “fu” should be wide and high, set the ratio of 1:1
app:layout_constraintDimensionRatio="1:1"
- Note: between controls
They have to be interdependent
To make a difference.
- Lateral weight
- The code is as follows:
<com.android.springfestival.view.VerticalTextView android:id="@+id/left" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginLeft="5dp" android:background="@drawable/shape_red_solid" Android :ems="1" Android :paddingTop="10dp" Android :paddingBottom="10dp" Android :textSize="24sp" android:textStyle="bold" app:layout_constraintHorizontal_weight="1" app:layout_constraintBottom_toTopOf="@id/guideline" app:layout_constraintEnd_toStartOf="@id/ling" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/top" /> <com.android.springfestival.view.VerticalTextView android:id="@+id/right" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginRight="5dp" android:background="@drawable/shape_red_solid" android:ems="1" android:paddingTop="10dp" android:paddingBottom="10dp" Android :text=" 24SP "Android :textSize=" 24SP" Android :textStyle="bold" app:layout_constraintHorizontal_weight="1" app:layout_constraintBottom_toBottomOf="@id/guideline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/ling" app:layout_constraintTop_toBottomOf="@id/top" /> <com.android.springfestival.view.DiamondTextView android:id="@+id/ling" android:layout_width="0dp" app:layout_constraintDimensionRatio="1:1" app:layout_constraintHorizontal_weight="3" android:layout_height="0dp" Android :layout_margin="5dp" Android :autoSizeTextType="uniform" Android :gravity="center" Android :text=" " android:textStyle="bold" app:layout_constraintBottom_toTopOf="@+id/OptionVp" app:layout_constraintEnd_toStartOf="@id/right" app:layout_constraintStart_toEndOf="@id/left" app:layout_constraintTop_toBottomOf="@id/top" />Copy the code
- The following
ViewPager2
andindicator
usingThe weight
, press the remaining space4:1
I’m going to distribute, right hereThe weight
andLinearLayout
Is consistent with.
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/OptionVp"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/llPointContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/guideline"
app:layout_constraintVertical_weight="4" />
<LinearLayout
android:id="@+id/llPointContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/OptionVp"
app:layout_constraintVertical_weight="1" />
Copy the code
Drawable used
- I’m going to use theta
ShapeDrawable
- Its advantage is that it can be used for controls
Add background
.To reduce
Image resourceuse
And thusReduced package volume
theThe size of the
.
- Its advantage is that it can be used for controls
- In the picture above
couplets
andStroke gold thread
All fromShapeDrawable
, the code is as follows
<? The XML version = "1.0" encoding = "utf-8"? > <shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="1dp" android:color="@color/colorGold" /> <solid android:color="@color/colorRed" /> </shape>Copy the code
The custom View
Horizontal batch
- I don’t know if you noticed,
The font
It’s not a system font, we’re going to change itThe font
The easiest way to do this isInherit the TextView
And rewrite hissetTypeface
methods
- New as above
directory
Put in what we needThe font
. Use this font
And,To the parent class
.- in
Layout file
In theuse
, the code inConstraintLayout
In the chapter.
class SpringTextView(context: Context? , attrs: AttributeSet?) Override fun setTypeface(tf: Typeface?); { super.setTypeface(Typeface.createFromAsset(context.assets, "fonts/hwxk.ttf")) } }Copy the code
couplets
- As I’m sure you all know,
TextView
You can useandroid:ems="1"
To achieveVertical array
, butStick together
.Can't divide
veryNot beautiful
So let’s move onInherit the TextView
, the customVertical equalization effect
.- This time we
Rewrite the onDraw method
Do it yourselfText drawing
. - height-drawn
The key point
Is thatFigure out the space between each text
(Total height minus the padding and width of the text divided by the number of text minus one
) - Width drawing (
Total width minus the width of the text divided by two
)
- This time we
- The code is as follows:
override fun onDraw(canvas: Canvas) { paint.textSize = textSize paint.apply { typeface = Typeface.createFromAsset(context.assets,"fonts/hwxk.ttf") } var textLengthHeight = 0 val r = Rect() val arr = IntArray(text.length) canvasLength = measuredHeight - paddingTop - paddingBottom if (! TextUtils.isEmpty(text) && text.length > 1) { var i = 0 while (i < text.length) { paint.getTextBounds(text.substring(i, i + 1), 0, 1, r) textLengthHeight += (r.bottom - r.top) arr[i] = r.bottom - r.top i++ } space = (canvasLength - textLengthHeight).toDouble() / (text.length - 1) } var arrlength = 0f var i = 0 while (i < text.length) { arrlength += arr[i] if (i == 0) { canvas.drawText( text.substring(i, i + 1), ((width - r.right - r.left) / 2).toFloat(), (i * space + arrlength).toFloat() + paddingTop, paint ) } else { canvas.drawText( text.substring(i, i + 1), ((width - r.right - r.left) / 2).toFloat(), (i * space + arrlength).toFloat(), paint ) } i++ } }Copy the code
everyone
The diamond TextView
The system didn’t give us anything. What do we do? Go onThe custom!
- Old rule
Rewrite the ontouch
To obtainWide high
, take the shortest, usePath
Let me draw oneTextView sets the background
Can. - Here I am
Drew twice
Because theeveryone
How could there be lessPhnom penh
!
- Old rule
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
var min = min(width, height)
var mPath = Path().apply {
moveTo(0F, (min / 2).toFloat());
lineTo((min / 2).toFloat(), 0F);
lineTo(min.toFloat(), (min / 2).toFloat());
lineTo((min / 2).toFloat(), min.toFloat());
close();
}
val bmp = Bitmap.createBitmap(min, min, Bitmap.Config.ARGB_8888)
val c = Canvas(bmp)
c.drawPath(mPath, paint)
c.drawPath(mPath, paintStock)
setBackgroundDrawable(BitmapDrawable(resources, bmp))
Copy the code
ViewPager2
- ViewPager2 before written a Banner to create the rotation of the map, here in a simple worded two sentences, may be some friends did not see the previous article.
The implementation of infinite sliding
- The first digit of the data source
add
Last picture
val newList = arrayListOf<String>()
newList.add(pic[pic.size-1])
Copy the code
- The last bit adds the first diagram
for (item in pic) {
newList.add(item)
}
newList.add(pic[0])
Copy the code
- when
ViewPager2 slides to bit 0
andThe last one
The treatment is as follows
location | To deal with |
---|---|
currentPosition == 0 |
setCurrentItem(adapter.itemCount - 2 , false) |
currentPosition == adapter.itemCount - 1 |
setCurrentItem(1 , false) |
ViewPager2
Add the slide listener code below
The key point is the onPageScrollStateChanged method
bannerVp.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { currentPosition = position } override fun onPageScrollStateChanged(state: Int) {// Only in idle state, If (state == viewPager2. SCROLL_STATE_IDLE) {if (currentPosition == 0) { bannerVp.setCurrentItem(adapter.itemCount - 2, false) } else if (currentPosition == adapter.itemCount - 1) { bannerVp.setCurrentItem(1, false) } } } })Copy the code
The shape of the item
- This is also through
ShapeDrawable
The code is as follows
<? The XML version = "1.0" encoding = "utf-8"? > <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:bottomRightRadius="50dp" android:topLeftRadius="50dp" /> <stroke android:width="1dp" android:color="@color/colorGold" /> <solid android:color="#F02A2A" /> </shape>Copy the code
Adding indicators
- According to the number of
Dynamically creating a View
, the code is as follows:
private fun initIndicator(){ llPointContainer.removeAllViews() for (index in 1.. size-2) { val view = View(this) val layoutParams = LinearLayout.LayoutParams(10.dp.toInt(), 10.dp.toInt()) layoutParams.marginEnd = 8 layoutParams.marginStart = 8 view.layoutParams = layoutParams llPointContainer.addView(view) } }Copy the code
- When you slide
Update indicator background
- in
ViewPager2
Slide listeningonPageSelected
Method to call the following method- Remember to do the following
judge
- Remember to do the following
- in
if (position <= llPointContainer.childCount) updateIndicator(position)
Copy the code
private fun updateIndicator(position: Int){ llPointContainer.run { for (index in 1.. childCount) { getChildAt(index - 1).background = resources.getDrawable(R.drawable.circlered) } if (position > 0) { getChildAt(position - 1).background = resources.getDrawable(R.drawable.circlegold) } } }Copy the code
- The shape here is also through
ShapeDrawable
The implementation.
ViewPager2 Multiple pages on one screen
- Here and
ViewPager
theMore than one screen page
There is a bigThe difference between
.ViewPager
Used forSelf set margin
And set theThe clipChildren property is false
. ViewPager2
By givingRecyclerView
Set up thePadding
andPageTransformer
To achieve
OptionVp.apply { offscreenPageLimit=1 val recyclerView= getChildAt(0) as RecyclerView recyclerView.apply { val padding = resources.getDimensionPixelOffset(R.dimen.common_line_height) + resources.getDimensionPixelOffset(R.dimen.common_line_height) // setting padding on inner RecyclerView puts overscroll effect in the right place setPadding(padding, 0, padding, 0) clipToPadding = false } }Copy the code
ViewPager2 slides to scale
- So that’s the point
PageTransformer
It can be used to setPage animation
, you can also setPage space
.Spacing and animation
If you want to useCompositePageTransformer
. - I like here
On a
To set upPage spacing and zooming
So let’s seeSpecific code
.
val compositePageTransformer = CompositePageTransformer()
compositePageTransformer.addTransformer(ScaleInTransformer())
compositePageTransformer.addTransformer(
MarginPageTransformer(
resources.getDimension(R.dimen.common_margin_middle).toInt()
)
)
OptionVp.setPageTransformer(compositePageTransformer)
Copy the code
- Isn’t it
Very sweet
Fast,To use!
.
The sensor
Android
There are a lot of sensors, and here we’re usingAcceleration sensor
, the procedure is as follows:- To obtain
Sensor manager
object - To obtain
Acceleration sensor
object registered
Sensors (onCreate
In the call)remove
Sensors (onDestory
In the call)
- To obtain
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
Copy the code
sensor = sensorManager!! .getDefaultSensor(Sensor.TYPE_ACCELEROMETER)Copy the code
sensorManager!! .registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)Copy the code
sensorManager!! .unregisterListener(this)Copy the code
- registered
The listener
After theonSensorChanged
Method to dobusiness
The judgment of (here use getEvent. Values greater than 15
) in accordance with the business conditionsCall to vibrate
andA dialog box is displayed.
.
Override fun onSensorChanged(event: SensorEvent) {override fun onSensorChanged(event: SensorEvent) {/* Function that is called when the sensor value changes */ val values: FloatArray = event.values val x = values[0] val y = values[1] val z = values[2] val minValue = 15 if(! IsShake) {if (Math. Abs (x) > minValue | | math.h abs (y) > minValue | | math.h abs (z) > minValue) {/ / vibration isShake = true val pattern = longArrayOf(300, 500) vibrator!! .vibrate(pattern, -1) MyDialog(this).showdialog (currentPosition-1)}}Copy the code
Realization of vibration
- The vibration needs to be
manifest
In the fileTo apply for permission
- To obtain
Vibrator manager
object - call
Vibrate Activates vibration
<! - vibrator access - > < USES - permission android: name = "android. Permission. VIBRATE" / >Copy the code
// Get vibrator manager object vibrator = getSystemService(VIBRATOR_SERVICE) as vibratorCopy the code
Val Pattern = longArrayOf(300, 500) vibrator!! .vibrate(pattern, -1)Copy the code
Android animation
- So here we’re using
The View animation
toDialog
addEntry and exit animations
. *The View animation
Like aPan, scale, rotate and transparence
This is used hereThe zoom
.
The label | meaning |
---|---|
interpolator | Accelerate_interpolator specifies animation interpolator. The common accelerate_interpolator is elerate_interpolator, decelerate interpolator. |
pivotX | Horizontal animation starting position, relative to the percentage of the screen, 50% indicates that the animation starts in the middle of the screen |
pivotY | The starting position of the vertical animation, relative to the percentage of the screen. 50% indicates that the animation starts in the middle of the screen |
fromXScale | Zoom before the start of the horizontal animation, 0.0 is not shown, 1.0 is normal size |
toXScale | The final zoom of the horizontal animation, 1.0 is the normal size, greater than 1.0 magnification |
fromYScale | Zoom before the start of vertical animation, 0.0 is not shown, 1.0 is normal size |
toYScale | The final zoom of the vertical animation, 1.0 is the normal size, greater than 1.0 magnification |
- With that in mind, what follows
Enter the animation
, andPlay the animation
It’s easier to understand- Center position
From zero to one
forThe zoom
.
- Center position
<! - when the pop-up animation -- -- > < set XMLNS: android = "http://schemas.android.com/apk/res/android" > < scale Android: interpolator = "@ android: anim/accelerate_interpolator" android: fromXScale = "0.0" android: toXScale = "1.0" Android :fromYScale="0.0" Android :toYScale="1.0" Android :pivotX="50%" Android :fillAfter="false" android:duration="400"/> </set>Copy the code
<! - exit animation effects - > < set XMLNS: android = "http://schemas.android.com/apk/res/android" > < scale Android: interpolator = "@ android: anim/accelerate_interpolator" android: fromXScale = "1.0" android: toXScale = "0.0" Android :fromYScale="1.0" Android :toYScale="0.0" Android :pivotX="50%" Android :fillAfter="false" android:duration="400"/> </set>Copy the code
- Exit from the
One to zero
Back to theCenter position
.
Random results
- There is no network request here
Write your answers locally
.A random sample
Display.random
The code inKotlin
It is very simple as follows
(answerList.indices).random()
Copy the code
- Originally wanted to add a database, support artificial input, the late slowly realize it.
The last
I wish you all the best in the year of the Tiger. I wish you all the best in 2022. After several revisions of my idea, I almost lost my baby.
Writing is not easy, if you have a drop of help or inspiration, thank you for your support, if you have a question, also welcome to leave a message!