在大量寻找自动调整 TextView 大小的最佳解决方案(根据内容、大小、最小和最大行数和字体大小限制)之后,我为这一切做了一个合并的解决方案,这里。
注意:我不使用其他解决方案,因为它们不能很好地工作,每个都有自己的问题(不支持某些内容,文本超出 TextView,文本被截断,...)。
演示它的工作原理:
https://raw.githubusercontent.com/AndroidDeveloperLB/AutoFitTextView/master/animationPreview.gif
在某些情况下,一行的最后一个字符会换行到下一行,例如:
绿色是 TextView 的边界,红色在它之外。
基本上,给定 TextView 的大小、它的最小和最大字体大小和最小和最大行数,以及应该在其中的内容(文本),它会找到(使用二进制搜索)什么字体大小应该适合 TextView 的边界。
该代码已经在 Github 中可用,但这里是为了以防万一:
public class AutoResizeTextView extends AppCompatTextView {
private static final int NO_LINE_LIMIT = -1;
private final RectF _availableSpaceRect = new RectF();
private final SizeTester _sizeTester;
private float _maxTextSize, _spacingMult = 1.0f, _spacingAdd = 0.0f, _minTextSize;
private int _widthLimit, _maxLines;
private boolean _initialized = false;
private TextPaint _paint;
private interface SizeTester {
/**
* @param suggestedSize Size of …Run Code Online (Sandbox Code Playgroud) 几个月前,谷歌发布了一个新的 API 来检测位图上的人脸:
它应该比内置的 FaceDetector 类更快更好,并且与它相比没有限制/局限性(例如需要输入位图配置为 565 ,位图宽度均匀,并且最大面部数探测)。
代码也非常简单:
显现:
<meta-data
android:name="com.google.android.gms.vision.DEPENDENCIES"
android:value="face" />
Run Code Online (Sandbox Code Playgroud)
爪哇:
FaceDetector faceDetector = new
FaceDetector.Builder(getApplicationContext()).setTrackingEnabled(false)
.build();
if(!faceDetector.isOperational()){
//show error
return;
}
Frame frame = new Frame.Builder().setBitmap(myBitmap).build();
SparseArray<Face> faces = faceDetector.detect(frame);
Run Code Online (Sandbox Code Playgroud)
似乎该 API 在某些设备上不可用,在调用“isOperational()”时返回“false”。
我发现了一些线索:
在Github(此处)上,其他人也发现了这个问题。
该示例 …
Google已使用Firebase Analytics和Firebase远程配置为A/B测试发布了全新的API和服务.
虽然我尝试将该服务用于其他目的(此处和此处),但我还需要将其用于A/B测试.
事实是,我无法找到如何让它显示分析实验变体结果所需的信息.
它只是没有显示(在这个网站上),或者我没有看到正确的地方:
为了尝试一个实验,我按照教程说我应该做的,包括:
boolean isDebug = AppComponentsHelper.isInDebugFlavour(context);
mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(isDebug).build();
mFirebaseRemoteConfig.setConfigSettings(configSettings);
final HashMap<String, Object> defaults = new HashMap<>();
for (ExperimentType experimentType : ExperimentType.values())
defaults.put(experimentType.experimentId, experimentType.defaultValues);
mFirebaseRemoteConfig.setDefaults(defaults);
long cacheExpiration = isDebug ? 0 : TimeUnit.HOURS.toSeconds(1);
mFirebaseRemoteConfig.fetch(cacheExpiration)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
mFirebaseRemoteConfig.activateFetched();
final FirebaseAnalytics firebaseAnalytics = FirebaseAnalytics.getInstance(context); …Run Code Online (Sandbox Code Playgroud)Html.fromHtml几乎没有任何关于它支持哪些标签的文档。
据报道,它确实支持许多网站上的“font”标签(如此处),但我无法找出在此标签内设置“face”属性时可用的字体。
我可以假设哪些字体始终可用?其中哪些仅来自特定的 Android 版本?某处有他们的名单吗?
编辑:看来答案应该在“/system/etc/fonts.xml”文件中。以下是 Android 6.0.1 上的内容:
<familyset version="22">
<!-- first font is default -->
<family name="sans-serif">
<font weight="100" style="normal">Roboto-Thin.ttf</font>
<font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
<font weight="300" style="normal">Roboto-Light.ttf</font>
<font weight="300" style="italic">Roboto-LightItalic.ttf</font>
<font weight="400" style="normal">Roboto-Regular.ttf</font>
<font weight="400" style="italic">Roboto-Italic.ttf</font>
<font weight="500" style="normal">Roboto-Medium.ttf</font>
<font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
<font weight="900" style="normal">Roboto-Black.ttf</font>
<font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
<font weight="700" style="normal">Roboto-Bold.ttf</font>
<font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
</family>
<!-- Note that aliases must come after the fonts they reference. -->
<alias name="sans-serif-thin" to="sans-serif" weight="100" />
<alias name="sans-serif-light" to="sans-serif" weight="300" …Run Code Online (Sandbox Code Playgroud) 到目前为止,使用此意图有一种简单的方法来安装APK文件:
final Intent intent=new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
Run Code Online (Sandbox Code Playgroud)
但是,如果你的应用程序中的Android API 24以上(牛轧糖- 7.0),你就可以或更新运行这段代码,你会得到一个异常,如图所示这里,例如:
android.os.FileUriExposedException: file:///storage/emulated/0/sample.apk exposed beyond app through Intent.getData()
Run Code Online (Sandbox Code Playgroud)
所以我做了我被告知的事情:使用支持库的FileProvider类,如下:
final Intent intent = new Intent(Intent.ACTION_VIEW)//
.setDataAndType(android.support.v4.content.FileProvider.getUriForFile(context,
context.getPackageName() + ".provider", apkFile),
"application/vnd.android.package-archive").addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Run Code Online (Sandbox Code Playgroud)
清单:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
Run Code Online (Sandbox Code Playgroud)
res/xml/provider_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!--<external-path name="external_files" path="."/>-->
<external-path
name="files_root"
path="Android/data/${applicationId}"/>
<external-path
name="external_storage_root"
path="."/>
</paths>
Run Code Online (Sandbox Code Playgroud)
但是,现在它仅适用于Android Nougat.在Android 5.0上,它抛出一个异常:ActivityNotFoundException.
我可以添加一个Android OS版本的检查,并使用任何一种方法,但正如我所读,应该使用一种方法:FileProvider.
所以,我尝试使用我自己的ContentProvider充当FileProvider,但我得到了与支持库的FileProvider相同的异常.
这是我的代码:
final Intent intent = new Intent(Intent.ACTION_VIEW)
.setDataAndType(OpenFileProvider.prepareSingleFileProviderFile(apkFilePath),
"application/vnd.android.package-archive")
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Run Code Online (Sandbox Code Playgroud)
OpenFileProvider.java …
android android-intent apk android-fileprovider android-7.0-nougat
从Android 6开始,每次安装应用程序时,都需要在运行时授予其权限。
从IDE运行应用程序时,这可能会变得非常烦人,因为每次尝试试用应用程序(如果未安装)时都需要重新授予权限,这是繁琐的操作,尤其是当您具有多个权限时。
当然,以这种方式测试应用程序也很重要,因为这是用户使用应用程序的方式,但是从某个时候开始就不需要了,因为您已经很好地处理了它
我唯一发现的是如何为此(此处)创建新的gradle任务,但这与安装不兼容。相反,我需要单独运行它,但是为此,无论如何,我只能使用adb命令使用批处理文件。
我发现(这里)的另一件事是做到这一点,但又由于某种原因在启动之前重新安装(这意味着您要两次安装该应用程序,而不是每次安装一次)。这不是一个好的解决方案。
有没有一种方法可以在通过IDE安装应用程序后自动授予所有权限?
我正在开发一个带有RecyclerView的应用程序,您可以根据需要上下滚动。
数据项是从服务器加载的,因此,如果您要到达底部或顶部,则应用程序将获取新数据以显示在那里。
为了避免奇怪的滚动行为并停留在当前项目上,我使用了' DiffUtil.Callback ',覆盖了'getOldListSize','getNewListSize','areItemsTheSame','areContentsTheSame'。
我在这里问过这个问题,因为我从服务器获得的只是一个全新的项目列表,而不是与上一个列表的区别。
RecyclerView没有仅要显示的数据。也有一些特殊的项目:
由于Internet连接速度可能很慢,因此RecyclerView中有一个标题项和一个脚注项,它们只有一个特殊的“进度”视图,以表明您已经到达边缘并且将很快加载。
页眉和页脚始终存在于列表中,并且不会从服务器收到它们。它纯粹是UI的一部分,只是为了显示即将加载的内容。
就像其他项一样,它需要由DiffUtil.Callback处理,因此对于areItemsTheSame和areContentsTheSame,如果旧页眉是新页眉,而旧页脚是新页脚,则只返回true:
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldItems[oldItemPosition]
val newItem = newItems[newItemPosition]
when {
oldItem.itemType != newItem.itemType -> return false
oldItem.itemType == ItemType.TYPE_FOOTER || oldItem.itemType == AgendaItem.TYPE_HEADER -> return true
...
}
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldItems[oldItemPosition]
val newItem = newItems[newItemPosition]
return when {
oldItem.itemType == ItemType.TYPE_FOOTER || …Run Code Online (Sandbox Code Playgroud) In order to go to the calendar at a specific time, we use this (based on this link) :
@Nullable
public static Intent prepareIntentForCalendar(final Context context, final Date date) {
Intent intent = null;
final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, date.getTime());
intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
final PackageManager pm = context.getPackageManager();
final ResolveInfo resolveActivity = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY
| PackageManager.GET_RESOLVED_FILTER);
if (resolveActivity == null)
return null;
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
return intent;
}
Run Code Online (Sandbox Code Playgroud)
Only if it's …
android android-intent android-calendar android-securityexception
我知道 Android Q 上有一项新功能可以最终支持黑暗主题(这里写了关于检测它的内容)。
我也知道有“夜灯”功能(这里)使屏幕变得更黄。
支持手动选择主题是我多年来所做的事情(在 Activity 的 onCreate 的第一行代码中简单地使用setTheme),但我想知道是否有一些自动的东西可以让我在应用程序真正启动之前设置它,在启动画面中。
似乎一个非常古老的功能(从 API 8 开始!)在 Android 上已经存在很长时间了,在资源中有“夜间”限定符,我什至从未尝试过。
可悲的是,因为“黑暗主题”和与夜间相关的东西现在更常被谈论为新功能(例如这里),我找不到旧功能的全部内容。
但是,查看一些文章和文档,它似乎几乎完全是手动的:
https://developer.android.com/reference/android/app/UiModeManager.html - 说我可以自己设置,包括设置为自动。然而,这似乎与停靠有关,甚至可能与汽车模式有关。
https://google-developer-training.github.io/android-developer-fundamentals-course-concepts/en/Unit%202/53_c_providing_resources_for_adaptive_layouts.html - 说我可以将“night”设置为限定符,并且有一个“夜间模式”。
我尝试相应地设置各种主题:
res/drawable/splash.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
<item android:gravity="fill">
<shape android:shape="rectangle">
<solid android:color="#fff"/>
</shape>
</item>
...
</layer-list>
Run Code Online (Sandbox Code Playgroud)
res/drawable-v29/splash.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
<item android:gravity="fill">
<shape android:shape="rectangle">
<solid android:color="?attr/colorSurface"/>
</shape>
</item>
...
</layer-list>
Run Code Online (Sandbox Code Playgroud)
res/drawable-night/splash.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:opacity="opaque" tools:ignore="UnusedAttribute">
<item android:gravity="fill">
<shape android:shape="rectangle"> …Run Code Online (Sandbox Code Playgroud) 我正在尝试拥有一个具有不同视图类型的 RecyclerView,但具有拖放功能以及单击和长按操作的能力。
它类似于您在电话应用程序上的功能,您可以在其中更改收藏夹项目的顺序。在电话应用程序中,当您长按某个项目时,会立即出现一个上下文菜单,如果您继续拖动,上下文菜单就会消失。
但是,在这种情况下,我需要做相反的事情。长按时,如果用户在很短的时间内没有拖动,或者用户在没有拖动的情况下停止长按,我们会在屏幕上显示一个对话框,我需要停止拖动过程。
虽然我已经成功地处理了长触摸机制,并且我在这些特殊情况下显示了一个对话框,但我未能使拖动停止。
这意味着,如果用户在对话框出现后继续触摸屏幕,仍然可以继续拖动:
整个代码在这里可用(没有长触摸行为的代码在这里可用),但这里是主要代码:
class MainActivity : AppCompatActivity() {
sealed class Item(val id: Long, val itemType: Int) {
class HeaderItem(id: Long) : Item(id, ITEM_TYPE_HEADER)
class NormalItem(id: Long, val data: Long) : Item(id, 1)
}
enum class ItemActionState {
IDLE, LONG_TOUCH_OR_SOMETHING_ELSE, DRAG, SWIPE, HANDLED_LONG_TOUCH
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val items = ArrayList<Item>(100)
var itemDataCounter = 0L
items.add(Item.HeaderItem(0L))
for (i in 0 until 100) {
items.add(Item.NormalItem(itemDataCounter, itemDataCounter))
++itemDataCounter …Run Code Online (Sandbox Code Playgroud) android ×10
ab-testing ×1
adb ×1
apk ×1
autoresize ×1
firebase ×1
font-face ×1
fonts ×1
gradle ×1
permissions ×1
textview ×1