Android开发中遇到的问题总结【持续更新】

目录

Android控件/框架开源库收集

配置国内仓库 

1. Java中设置控件的大小需要把dp先转换为像素(转换如下)

2. Java中设置GridLayout布局的layout_columnWeight属性

3. 设置字体样式为粗体 

4. 设置字体颜色为黑色,但显示的是灰色。【使用以下写法设置即可】

5. Java代码中设置TextView的drawable不生效问题

6. 图标使用图片格式模糊,可使用以下方式改善【前提是需要svg源文件】 

7. 加了layout_weight="1"的权重,只有一个元素怎么让它只占一半?

8. 为什么GridLayout布局中加了layout_columnWeight="1"还是超出了屏幕大小?

9. 有头像的情况下展示头像,没有头像的情况下展示用户的名字。 

10.  Toolbar内标题的字体加粗设置

11. 使用CardView后有四周出现多出的空白

12. LinearLayout布局内的组件设置layout_gravity="right"无效 

13. 在Fragment中处理返回事件,官方例子 

14.  ListView布局的一些问题

15. 去除WebView按钮聚焦时出现的黄框 

16. 获取显示在当前Activity的Fragment

17. NumberPicker设置item的颜色和大小以及分隔线的厚度和颜色 

18. 修改TextView和EditText中的hint字体大小 

19. 设置BottomSheetDialog向下滑动不关闭弹窗并保留点击背景时才关闭弹窗

20. 原生TabLayout调用getOrCreateBadge报错

21. 根据重力感应自动横竖屏切换,并且不走生命周期 

22. Android中一个Activity关闭另一个Activity或者在一个Activity中关闭多个Activity

23. 跑马灯效果实现 

24.  TextView内容超过一定字数则显示...

25. BottomSheetDialog内放两个RecyclerView时,一个可以滑动,一个不能滑动

26. 选择照片或拍照上传

27.  当Activity、Fragment、PopupWindow内的EditText失去焦点后隐藏输入法(软键盘)

28. 不使用字符串拼接或分割的方式如何给url追加参数和获取参数

29. 使用dataBinding在xml中进行判断,隐藏某个控件的条件成立时,控件先出现一会后才隐藏的问题


Android控件/框架开源库收集


配置国内仓库 

maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}

https://maven.aliyun.com/repository/public其实包括了central仓库和jcenter仓库 


1. Java中设置控件的大小需要把dp先转换为像素(转换如下)

dp * this.getResources().getDisplayMetrics().density + 0.5

2. Java中设置GridLayout布局的layout_columnWeight属性

GridLayout.LayoutParams param = new GridLayout.LayoutParams();
param.columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f);
param.width = 0;
view.setLayoutParams(param);

3. 设置字体样式为粗体 

textView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));

4. 设置字体颜色为黑色,但显示的是灰色。【使用以下写法设置即可】

textView.setTextColor(getResources().getColor(R.color.black));

5. Java代码中设置TextView的drawable不生效问题

Drawable drawable = getResources().getDrawable(R.drawable.tttt);
// 添加setBounds即可
drawable.setBounds(0,0,drawable.getMinimumWidth(),drawable.getMinimumHeight());
textView.setCompoundDrawables(drawable,null,null,null);

6. 图标使用图片格式模糊,可使用以下方式改善【前提是需要svg源文件】 

假如我需要的图标在阿里的iconfont上有,那么可以选择下载svg格式的,如下:

接着需要在Android Studio中自带的工具进行转换,转换操作如下:

转换结果如下: 

 接着只需要引用对应的文件名即可使用。。。


7. 加了layout_weight="1"的权重,只有一个元素怎么让它只占一半?

在LinearLayout中添加属性android:weightSum="2"即可,如下: 


8. 为什么GridLayout布局中加了layout_columnWeight="1"还是超出了屏幕大小?

 设置layout_columnWeight="1"的同时也要设置layout_width="0dp",这样即可解决,在线性布局中设置的layout_weight="1"也跟上面一样将宽度值设为0dp即可!

GridLayout布局中有个坑:假设我添加了一个columnCount为2的值,但是这个布局里只有一个控件的话即使设置了layout_columnWeight的值为1,它还是会占一整行!用线性布局的话不会出现这个问题。 


9. 有头像的情况下展示头像,没有头像的情况下展示用户的名字。 

我的实现方式是通过FrameLayout来实现,至于显示图像还是文字,在代码中进行控制

xml: 

<FrameLayout
        android:id="@+id/avatar_container"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@drawable/circle_background"
        android:padding="1dp" />

 创建一个名为circle_background.xml的可绘制资源文件,用于绘制圆形背景和边框。在res/drawable目录下创建该文件,并添加以下内容:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 背景色 -->
    <solid android:color="@color/blue_1682C9" />
    <!-- 实现描边效果 -->
    <stroke
        android:width="1dp"
        android:color="@android:color/white" />
    <!-- 圆角 -->
    <corners android:radius="50dp" />
</shape>

 代码中控制显示图像还是文字的示例:

FrameLayout avatarContainer = findViewById(R.id.avatarContainer);

// 设置图像
if (hasImage) {
    ImageView avatarImageView = new ImageView(this);
    avatarImageView.setLayoutParams(new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));
    avatarImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    avatarImageView.setImageResource(R.drawable.custom_avatar_image);
    
    // 清除文本
    avatarContainer.removeAllViews();
    // 添加图像视图
    avatarContainer.addView(avatarImageView);
}
// 设置文字
else {
    TextView avatarTextView = new TextView(this);
    avatarTextView.setLayoutParams(new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT));
    avatarTextView.setGravity(Gravity.CLIP_VERTICAL | Gravity.CENTER_HORIZONTAL);
    avatarTextView.setText("A");
    avatarTextView.setTextColor(getResources().getColor(R.color.white));
    
    // 清除图像
    avatarContainer.removeAllViews();
    // 添加文本视图
    avatarContainer.addView(avatarTextView);
}

10.  Toolbar内标题的字体加粗设置

在themes.xml里添加以下样式: 

<style name="HeaderToolbarStyle">
    <!-- 字体大小 -->
    <item name="android:textSize">18sp</item>
    <!-- 加粗 -->
    <item name="android:textStyle">bold</item>
    <!-- 字体颜色 -->
    <item name="android:textColor">@color/black</item>
    <!--toolbar字体格式-->
    <item name="android:typeface">sans</item>
</style>

 引用即可,如下图:


11. 使用CardView后有四周出现多出的空白

将cardPreventCornerOverlap属性设为false即可解决


12. LinearLayout布局内的组件设置layout_gravity="right"无效 

这是因为LinearLayout默认是水平方向的布局,当水平方向时只有top和bottom有效,垂直方向布局时left和right才有效,所以我们需要给LinearLayout的orientation属性设为vertical即可


13. 在Fragment中处理返回事件,官方例子 

public class FormEntryFragment extends Fragment {
        @Override
       public void onAttach( @NonNull Context context) {
           super.onAttach(context);
           OnBackPressedCallback callback = new OnBackPressedCallback(
               true // default to enabled
           ) {
                @Override
               public void handleOnBackPressed() {
                   // TODO 触发后的逻辑
               }
           };
           requireActivity().getOnBackPressedDispatcher().addCallback(
               this, // LifecycleOwner
               callback);
       }
   }

14.  ListView布局的一些问题

当我在ListView控件下添加一个Button控件时,Button控件一直溢出屏幕,如下图:

要解决该问题需要为ListView控件添加android:layout_weight="1"的属性,以及把高度设为0dp即可解决,效果如下图:

注意:我的布局是在LinearLayout当中的!!! 


15. 去除WebView按钮聚焦时出现的黄框 

在页面中添加以下css样式即可解决 

  .xxx{
    outline: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    -webkit-focus-ring-color: rgba(0, 0, 0, 0);
  }
  .xxx:active{
    outline: none;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    -webkit-focus-ring-color: rgba(0, 0, 0, 0);
  }

16. 获取显示在当前Activity的Fragment

首先你需要找到当前Activity的布局文件,要知道你的Fragment是放在哪个FrameLayout下的,比如我的Fragment是放在这个FrameLayout下,如图(注意id)

 接着只需要在你的Activity加上下面这段代码即可获取:

// 注意你的id是布局文件中FrameLayout标签的id
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.layout);

17. NumberPicker设置item的颜色和大小以及分隔线的厚度和颜色 

在themes.xml中添加以下的主题样式:

<!-- 时间选择器分隔线样式主题 -->
    <style name="NumberPickerTheme">
        <!--字体大小-->
        <item name="android:textSize">14sp</item>
        <!--字体颜色-->
        <item name="android:textColorPrimary">@color/black_333</item>
        <!--分隔线颜色-->
        <item name="colorControlNormal">#2B000000</item>
    </style>

接着在控件当中引用即可:

<!--selectionDividerHeight设置的是分隔线的厚度-->
<NumberPicker
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:selectionDividerHeight="1px"
    android:theme="@style/NumberPickerTheme" />

18. 修改TextView和EditText中的hint字体大小 

使用以下方法即可:

/**
 * 设置文本视图提示文本大小
 *
 * @param textView TextView
 * @param hint 提示内容
 * @param hintTextSize 提示文字大小
 */
public static void setTextViewHintTextSize(TextView textView, String hint, int hintTextSize) {
    SpannableString spannableString = new SpannableString(hint);
    AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(hintTextSize, true);
    spannableString.setSpan(absoluteSizeSpan, 0, spannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    textView.setHint(new SpannableString(spannableString));
}

19. 设置BottomSheetDialog向下滑动不关闭弹窗并保留点击背景时才关闭弹窗

bottomSheetDialog.getBehavior().setHideable(false);

20. 原生TabLayout调用getOrCreateBadge报错

报错信息:

 The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).

译文:

此组件的样式要求您的应用主题为 Theme.MaterialComponents(或后代)。

我们只需要给TabLayout组件设置上主题即可,如下图:

android:theme="@style/Theme.MaterialComponents.Light.NoActionBar"

21. 根据重力感应自动横竖屏切换,并且不走生命周期 

在AndroidManifest.xml中给需要自动横竖屏切换的activity添加以下配置:

android:configChanges="orientation|keyboardHidden|screenSize"

相关文章:Android横竖屏切换工具 - 掘金 


22. Android中一个Activity关闭另一个Activity或者在一个Activity中关闭多个Activity

参考链接:Android中一个Activity关闭另一个Activity或者在一个Activity中关闭多个Activity - 知乎 


23. 跑马灯效果实现 

<TextView
    android:id="@+id/marquee_textview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:ellipsize="marquee"
    android:fadingEdge="horizontal"
    android:marqueeRepeatLimit="marquee_forever"
    android:scrollHorizontally="true"
    android:singleLine="true"
    android:text="这是一个长文本跑马灯效果的示例,你可以在这里显示你的长文本内容。"
  • android:ellipsize="marquee":设置文本超出视图宽度时的处理方式为滚动。
  • android:fadingEdge="horizontal":为文本的左右两边添加淡出效果。
  • android:marqueeRepeatLimit="marquee_forever":设置跑马灯的滚动次数为无限次。
  • android:scrollHorizontally="true":让文本可以水平滚动。
  • android:singleLine="true":让所有文本都在一行内显示。

代码中添加:

TextView marqueeText = (TextView) this.findViewById(R.id.marquee_textview);
// 不加这个没有跑马灯效果
marqueeText.setSelected(true);

如果你是在Fragment中使用还需要在onDestroyView中将值设置成false,如果你是在Activity中使用则在onDestroy中设置,否则可能有内存泄露

marqueeText.setSelected(false);

24.  TextView内容超过一定字数则显示...

android:maxLines="1"
android:ellipsize="end"
android:maxEms="11"

25. BottomSheetDialog内放两个RecyclerView时,一个可以滑动,一个不能滑动

BottomSheetDialog是可以进行滑动关闭的,而滑动是由BottomSheetBehavior实现的,在BottomSheetBehavior的内部又控制了视图内只允许一个可滑动的控件,所以才会出现这种情况。你可以在不可滑动的RecyclerView控件添加,

android:nestedScrollingEnabled="false"

或者在代码中控制

ViewCompat.setNestedScrollingEnabled(recyclerView1, false)

你会发现这个时候它可以滑动了,但另一个就不能滑动了。网上一堆其他嵌套控件的方式,我用了没效果,改成使用PopupWindow就都正常了

26. 选择照片或拍照上传

跳转拍照的例子:

ActivityResultRegistry registry =
                        ((androidx.activity.ComponentActivity)activity).getActivityResultRegistry();
                    registry.register("testfile", new ActivityResultContracts.TakePicture(), result -> {
                        // 如果图像被保存到给定的Uri中,则result返回true
                    }).launch(uri);

跳转选择照片(单选):

ActivityResultRegistry registry =
                        ((androidx.activity.ComponentActivity)activity).getActivityResultRegistry();
                    registry.register("testfile", new ActivityResultContracts.GetContent(), result -> {
                        Log.i("image", result.get(0).getPath());
                    }).launch("image/*");

跳转选择照片的例子(多选):

ActivityResultRegistry registry =
                        ((androidx.activity.ComponentActivity)activity).getActivityResultRegistry();
                    registry.register("testfile", new ActivityResultContracts.GetMultipleContents(), result -> {
                        Log.i("image", result.get(0).getPath());
                    }).launch("image/*");

选择照片后返回的是Uri,如果你需要将图片上传到服务端,还需要获取到真实的文件才可,下面的方法是一个例子。ActivityResultRegistry除了上面的使用方式外还能够用来申请权限,用处还有很多。

Uri转File:

@RequiresApi(api = Build.VERSION_CODES.Q)
public static File uriToFileApiQ(Context context, Uri uri) {
    File file = null;
    // android10以上转换
    if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
        file = new File(uri.getPath());
    } else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
        // 把文件复制到沙盒目录
        ContentResolver contentResolver = context.getContentResolver();
        String displayName = System.currentTimeMillis() + Math.round((Math.random() + 1) * 1000) + "."
            + MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));
        file = new File(context.getCacheDir().getAbsolutePath(), displayName);
        try (InputStream is = contentResolver.openInputStream(uri);
            FileOutputStream fos = new FileOutputStream(file)) {
            FileUtils.copy(is, fos);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return file;
}

如果你需要更丰富的功能,可以看下这个库:https://github.com/LuckSiege/PictureSelector

27.  当Activity、Fragment、PopupWindow内的EditText失去焦点后隐藏输入法(软键盘)

当Fragment所在的Activity已经实现后相应的效果也会在Fragment中展现,因此我们只需要在Activity中实现即可

 Activity:

@Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
                View v = getCurrentFocus();
                if (isShouldHideKeyboard(v, ev)) {
                    KeyboardUtils.hideSoftInput(this);
                }
            }
            return super.dispatchTouchEvent(ev);
        }


        private boolean isShouldHideKeyboard(View v, MotionEvent event) {
            if ((v instanceof EditText)) {
                int[] l = {0, 0};
                v.getLocationOnScreen(l);
                int left = l[0],
                        top = l[1],
                        bottom = top + v.getHeight(),
                        right = left + v.getWidth();
                return !(event.getRawX() > left && event.getRawX() < right
                        && event.getRawY() > top && event.getRawY() < bottom);
            }
            return false;
        }

 PopupWindow:

popupWindow.setTouchInterceptor(new View.OnTouchListener() {
                @SuppressLint("ClickableViewAccessibility")
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        View view = popupWindow.getContentView().findFocus();
                        if (view instanceof EditText) {
                            Rect outRect = new Rect();
                            view.getGlobalVisibleRect(outRect);
                            if (!outRect.contains((int) event.getRawX(), (int) event.getRawY())) {
                                view.clearFocus();
                                InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
                                imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
                            }
                        }
                    }
                    return false;
                }
            });

28. 不使用字符串拼接或分割的方式如何给url追加参数和获取参数

追加参数:

// 构建一条链接
Uri uri = new Uri.Builder()
        .scheme("http")
        .authority("domain.com")
        .path("uri")
        .appendQueryParameter("param1", "参数1")
        .appendQueryParameter("param2", "参数2")
        .build();
// 在现有的连接上追加参数
String url = new Uri.Builder()
        .path("http://domain.com/uri")
        .appendQueryParameter("param1", "参数1")
        .appendQueryParameter("param2", "参数2")
        .build().toString();

获取参数:

// 第一种
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(url);
String param1 = sanitizer.getValue("param1");
// 第二种
String param2 = Uri.parse(url).getQueryParameter("param2");

29. 使用dataBinding在xml中进行判断,隐藏某个控件的条件成立时,控件先出现一会后才隐藏的问题

比如以下控件:

<TextView
        android:id="@+id/error"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:focusable="true"
        android:gravity="center"
        android:text="加载错误,点击刷新"
        android:visibility="@{loadResult == LoadResult.error? View.VISIBLE:View.GONE}" />

首次刷新的时候这个控件是满足隐藏的条件的,但是该控件在出现一会后才隐藏。出现这个问题的原因是虽然已经给loadResult变量绑定了数据,但却还没立即执行,而是挂起等待了。我们可以手动调用下立即执行的方法即可解决这个问题。

binding.executePendingBindings();

 要在绑定数据后调用才有效果。


👍点赞,你的认可是我创作的动力 !
🌟收藏,你的青睐是我努力的方向!
✏️评论,你的意见是我进步的财富!  

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦境游子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值