我需要像“电话”应用上那样制作类似于拨号盘的视图。
我正在使用View的GridLayout。每个单元格的大小相同,并且仅包含一个简单的TextView,应在需要时更改其字体大小。
我已经成功了,但是由于某些原因,根据给定的空间,它不能很好地工作。
如果有很多空间,则可以正常工作:
但是,当它变小时(例如,小屏幕,风景,分割窗口...),只有网格的顶部按钮才可见,并且它们甚至都没有改变其字体大小,就好像它们都是希望拥有最大的尺寸:
我试图修改视图的各种属性,但没有帮助。
不过,我知道Phone应用程序的拨号盘并没有真正改变其字体大小。达到一定大小后,它会正常显示,如果太小,它将更改为其他布局。这对于横向和拆分窗口模式尤其重要。
这是我编写的代码(我更改了“ layout_constraintHeight_percent”的值以检查顶部区域的各种尺寸):
渐变
...
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.gridlayout:gridlayout:1.0.0'
...
QueryKeyboard.kt
class QueryKeyboard @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : GridLayout(context, attrs, defStyle) {
init {
orientation = HORIZONTAL
clipChildren = false
clipToPadding = false
columnCount = 3
rowCount = 4
//workaround for a weird issue of seeing just 3 huge buttons, instead of all
val runnable = Runnable {
for (i in 1..9)
addView(generateGridTextButton(i.toString()))
addView(generateGridTextButton("*"))
addView(generateGridTextButton("0"))
addView(generateGridTextButton("+"))
}
if (isInEditMode)
runnable.run()
else
this.doOnPreDraw { runnable.run() }
}
private fun generateGridTextButton(textToShowAndAddUponClick: CharSequence): TextView {
val tv = LayoutInflater.from(context).inflate(R.layout.grid_text_button, this, false) as TextView
tv.text = textToShowAndAddUponClick
return tv
}
}
grid_text_button.xml
<androidx.appcompat.widget.AppCompatTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:breakStrategy="balanced"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="false"
android:gravity="center"
android:textColor="#000"
android:textSize="36dp"
app:autoSizeMaxTextSize="36dp"
app:autoSizeMinTextSize="12dp"
app:layout_columnWeight="1"
app:layout_gravity="fill"
app:layout_rowWeight="1"
tools:layout_gravity="center"
tools:targetApi="m"
tools:text="1" />
activity_main.xml 中的用法:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity">
<TextView
android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="0px"
android:background="#33ff0000" android:gravity="center" android:text="some content"
app:layout_constraintBottom_toTopOf="@id/queryKeyboard" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.6" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.sample.myapplication.QueryKeyboard
android:id="@+id/queryKeyboard" android:layout_width="match_parent" android:layout_height="0px"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
编辑:我试图用FrameLayout包装TextView,以显示每个单元格的大小:
grid_text_button.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content"
app:layout_columnWeight="1" app:layout_gravity="fill" app:layout_rowWeight="1">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless" android:breakStrategy="balanced"
android:clickable="true" android:focusable="true" android:focusableInTouchMode="false" android:gravity="center"
android:textColor="#000" android:textSize="36sp" app:autoSizeMaxTextSize="36sp" app:autoSizeMinTextSize="12sp"
tools:layout_gravity="center" tools:targetApi="m" tools:text="1" />
</FrameLayout>
QueryKeyboard.kt
class QueryKeyboard @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : GridLayout(context, attrs, defStyle) {
private var cellBackgroundColor = 0xffff0000.toInt()
init {
orientation = HORIZONTAL
clipChildren = false
clipToPadding = false
columnCount = 3
rowCount = 4
//workaround for a weird issue of seeing just 3 huge buttons, instead of all
val runnable = Runnable {
for (i in 1..9) {
addView(generateGridTextButton(i.toString()))
}
addView(generateGridTextButton("*"))
addView(generateGridTextButton("0"))
addView(generateGridTextButton("+"))
}
if (isInEditMode)
runnable.run()
else
this.doOnPreDraw { runnable.run() }
}
private fun switchColor() {
cellBackgroundColor = if (cellBackgroundColor == 0xffff0000.toInt()) 0xff00ff00.toInt() else 0xffff0000.toInt()
}
private fun generateGridTextButton(textToShowAndAddUponClick: CharSequence): View {
val view = LayoutInflater.from(context).inflate(R.layout.grid_text_button, this, false)
switchColor()
view.setBackgroundColor(cellBackgroundColor)
view.textView.text = textToShowAndAddUponClick
return view
}
}
这是两种情况,什么时候可以正常工作,什么时候不可以:
与以前相同。获取3个单元格,文本不居中,并且不会自动调整其字体大小。
为什么单元格不调整其大小,包括每个单元格的字体大小?当它太小时,我怎么会只看到3个单元格?我该如何解决?
还有更好的选择吗?我想我可以使用多个LinearLayout实例的LinearLayout,但这在这种情况下很奇怪...毕竟,您多久使用一次GridLayout ...:)
如何检测它何时太小,以至于我切换到另一个布局(例如在Phone应用程序上),包括它们使用的所有各种情况(甚至是分割窗口)?他们是否可能仅将限定符用于布局?如果是这样,在这种情况下推荐使用哪种方法?
答案 0 :(得分:0)
为什么单元格不调整其大小,包括每个单元格的字体大小?我该如何解决?
一个单元可以基于两个主要约束条件动态调整其大小:the weight of its parent
和the value of its textsize or childview
。单元格上的文本大小固定会导致设计不一致。要解决此问题,您可以在父视图上设置宽度和高度与父级匹配的单元格的布局权重,也可以为目标设备创建不同尺寸的textsize。
还有更好的选择吗?我猜我可以使用多个LinearLayout实例的LinearLayout,但是在这种情况下这很奇怪...毕竟,您多久使用一次GridLayout ...:)
有一个更好的方法,那就是您当前正在实现的The GridLayout
。使用缩进的LinearLayouts会限制您很多好处,并使您编写更多代码,例如需要切换或设置单元格动画,访问第n行的第n列,动态更改单元格跨度等情况。通过Gridlayout用几行代码完成。它比您想像的还要强大。
如何检测它何时太小,以至于我切换到另一个布局(例如在Phone应用程序上),包括它们使用的所有各种情况(甚至是分割窗口)?他们是否可能仅将限定符用于布局?如果是这样,建议在这种情况下使用哪种方法?
您无需检测任何东西,只需遵循指南,Android就会进行检测。
有两种方法可以根据Android Design guidelines
管理方案 第一:
为您的活动(layout/activity.xml
和layout-land/activity.xml
)创建布局横向和纵向模式
layout / activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="2"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#33ff0000"
android:gravity="center" android:text="some content"
android:layout_weight="1" />
<com.sample.myapplication.QueryKeyboard
android:id="@+id/queryKeyboard"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
layout-land / activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="2"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#33ff0000"
android:gravity="center" android:text="some content"
android:layout_weight="1" />
<com.sample.myapplication.QueryKeyboard
android:id="@+id/queryKeyboard"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
此外,您需要处理各种屏幕尺寸的文本大小。
通过将Intuit android library添加到gradle的依赖项列表中,可以自动处理此textsize计算
dependencies {
implementation 'com.intuit.ssp:ssp-android:1.0.6'
}
然后在网格按钮中调用文本大小
android:textSize="@dimens/_30ssp"
答案 1 :(得分:0)
好,我对布局文件做了一些更改,以避免出现3单元问题。它仍然会发生,但是尺寸要小得多。可悲的是,字体大小问题仍然存在,甚至这次很小。
如果有人找到原因,请告诉我。目前,我认为这是一个错误,因此我报告了here。
grid_text_button.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:focusable="true" android:focusableInTouchMode="false" app:layout_columnWeight="1"
app:layout_gravity="fill" app:layout_rowWeight="1" tools:layout_gravity="center">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:breakStrategy="balanced" android:gravity="center"
android:textColor="#000" app:autoSizeMaxTextSize="36sp" app:autoSizeMinTextSize="12sp" tools:targetApi="m"
tools:text="1" />
</FrameLayout>
QueryKeyboard.kt
class QueryKeyboard @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : GridLayout(context, attrs, defStyle) {
// private var cellBackgroundColor = 0xffff0000.toInt()
init {
orientation = HORIZONTAL
clipChildren = false
clipToPadding = false
columnCount = 3
rowCount = 4
for (i in 1..9)
addView(generateGridTextButton(i.toString()))
addView(generateGridTextButton("*"))
addView(generateGridTextButton("0"))
addView(generateGridTextButton("+"))
}
// private fun switchColor() {
// cellBackgroundColor = if (cellBackgroundColor == 0xffff0000.toInt()) 0xff00ff00.toInt() else 0xffff0000.toInt()
// }
private fun generateGridTextButton(textToShowAndAddUponClick: CharSequence): View {
val view = LayoutInflater.from(context).inflate(R.layout.grid_text_button, this, false)
// switchColor()
// view.setBackgroundColor(cellBackgroundColor)
view.textView.text = textToShowAndAddUponClick
return view
}
}
GridLayout实现的替代方法没有这个问题,但是我仍然很奇怪地使用它,就像我写的那样,是LinearLayouts的LinearLayout:
class QueryKeyboard2 @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : LinearLayout(context, attrs, defStyleAttr) {
//private var cellBackgroundColor = 0xffff0000.toInt()
init {
orientation = VERTICAL
clipChildren = false
clipToPadding = false
val columnCount = 3
val rowCount = 4
val cellsList = ArrayList<View>()
for (i in 1..9)
cellsList.add(generateGridTextButton(i.toString()))
cellsList.add(generateGridTextButton("*"))
cellsList.add(generateGridTextButton("0"))
cellsList.add(generateGridTextButton("+"))
for (i in 0 until rowCount) {
val rowLayout = generateRowLayout(context)
for (j in 0 until columnCount) {
val cellView = cellsList[i * columnCount + j]
val cellLayoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT)
cellLayoutParams.weight = 1f
rowLayout.addView(cellView, cellLayoutParams)
}
// switchColor()
// rowLayout.setBackgroundColor(cellBackgroundColor)
addView(rowLayout)
}
}
private fun generateRowLayout(context: Context): LinearLayout {
val result = LinearLayout(context)
result.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0)
(result.layoutParams as LayoutParams).weight = 1f
result.orientation = HORIZONTAL
return result
}
//private fun switchColor() {
// cellBackgroundColor = if (cellBackgroundColor == 0xffff0000.toInt()) 0xff00ff00.toInt() else 0xffff0000.toInt()
//}
private fun generateGridTextButton(textToShowAndAddUponClick: CharSequence): View {
val view = LayoutInflater.from(context).inflate(R.layout.grid_text_button, this, false)
//switchColor()
//view.setBackgroundColor(cellBackgroundColor)
view.textView.text = textToShowAndAddUponClick
return view
}
}
至于试图使其仅在有足够的空间(高度)时显示,我将布局设置为在“ res / layout-h400dp”上使用(可以根据需要进行更改),一种,通常是“ res / layout”的拨号盘在右侧。