Android textView 显示: STRING_TOO_LARGE

解决Android中STRING_TOO_LARGE错误:处理大字符串策略
本文讲述了在Android中遇到STRING_TOO_LARGE错误的原因,即字符串资源长度超过32KB。提供了三种解决方案:分割大字符串、使用WebView显示文本以及通过Assets加载文本文件。

在Android中,字符串资源的长度限制是32KB,getString()方法返回的字符串资源的大小超过这个限制,就会抛出STRING_TOO_LARGE 这个错误。

我本地的临界值是:32.3 KB (33,090 字节)

小于等于33090时,能正常显示;大于33090时,显示:STRING_TOO_LARGE。

<string content=" ...."/>

问题点是:getResource().getString(R.string.content) 得到的是:STRING_TOO_LARGE。

如果你需要显示更大的字符串,你可以尝试以下几种解决方案:

1、分割字符串:你可以尝试将大字符串分割成几个小字符串,然后分别在TextView中显示。这可以通过在字符串的特定位置使用分隔符来实现。
例如:

String largeText = "This is a very large string...";  
String[] smallerTexts = largeText.split("...");  
for (String text : smallerTexts) {  
    TextView textView = new TextView(this);  
    textView.setText(text);  
}

2、使用WebView:

如果你需要显示非常大的文本,可能需要考虑使用WebView而不是TextView。WebView没有字符限制,但它的性能开销可能会稍大一些。

3、使用Assets:
在这里插入图片描述


    private String getTextFromAssets() {
        try {
            AssetManager assetManager = this.getResources().getAssets();
            InputStream inputStream = assetManager.open("disclaimer_content.txt");
            byte[] data = new byte[inputStream.available()];
            inputStream.read(data);
            String largeText = new String(data, "UTF-8");
            return largeText.replace("\\n", "\n");
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }

    }
    public  String getStringFromAssets() {
        String str = "";
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(this.getResources().getAssets().open("disclaimer_content.txt"), "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String line;
            StringBuilder stringBuilder = new StringBuilder();
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
            bufferedReader.close();
            inputStreamReader.close();
            str = stringBuilder.toString().replace("\\n", "\n");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }


/********************************************************************* * * Copyright (C), 2010-2022 Oplus. All rights reserved.. * * VENDOR_EDIT * * File : AddFilePanelFragment.kt * * Description : AddFilePanelFragment * * Version : 1.0 * * Date : 2025/02/08 * * Author : W9085798 * * * * ---------------------Revision History: ---------------------------- * * <author> <data> <version> <desc> ***********************************************************************/ package com.oplus.filemanager.addfilepanel.ui import android.annotation.SuppressLint import android.app.Activity import android.os.SystemClock import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.RelativeLayout import android.widget.TextView import androidx.annotation.VisibleForTesting import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Lifecycle import androidx.lifecycle.ViewModelProvider import com.coui.appcompat.button.COUIButton import com.coui.appcompat.button.SingleButtonWrap import com.coui.appcompat.contextutil.COUIContextUtil import com.coui.appcompat.panel.COUIBottomSheetDialog import com.coui.appcompat.panel.COUIBottomSheetDialogFragment import com.coui.appcompat.panel.COUIPanelFragment import com.coui.appcompat.panel.COUIPanelMultiWindowUtils import com.coui.appcompat.tablayout.COUITab import com.coui.appcompat.tablayout.COUITabLayout import com.coui.appcompat.toolbar.COUIToolbar import com.filemanager.common.MyApplication.appContext import com.filemanager.common.base.BaseFileBean import com.filemanager.common.base.BaseFragmentAdapter import com.filemanager.common.constants.Constants import com.filemanager.common.controller.LoadingController import com.filemanager.common.controller.PrivacyPolicyController import com.filemanager.common.helper.MimeTypeHelper import com.filemanager.common.helper.uiconfig.UIConfigMonitor import com.filemanager.common.utils.Injector import com.filemanager.common.utils.KtViewUtils import com.filemanager.common.utils.Log import com.filemanager.common.utils.ModelUtils import com.filemanager.common.utils.SdkUtils import com.filemanager.common.utils.StatusBarUtil import com.filemanager.common.utils.Utils import com.filemanager.common.utils.dp2px import com.filemanager.common.view.ViewPagerWrapperForPC import com.filemanager.common.view.viewpager.RTLViewPager import com.oplus.filemanager.addfilepanel.R import com.oplus.filemanager.addfilepanel.bean.AddFileBean import com.oplus.filemanager.addfilepanel.viewmodel.AddFilePanelViewModel import com.oplus.filemanager.interfaze.categorydoc.IDocumentExtensionType import com.oplus.filemanager.interfaze.main.IMain import kotlin.properties.Delegates class AddFilePanelFragment : COUIPanelFragment(), COUITabLayout.OnTabSelectedListener, PrivacyPolicyController.OnPrivacyPolicyListener { companion object { private const val TAG = "ShortcutFolderAddFilePanelFragment" private const val NUM = 1024 private const val DECIMAL_NUM = 1024f private const val DISMISS_TIME_GAP = 1000L private const val DELAY_TIME = 50L private const val PANEL_MAX_HEIGHT = "panel_max_height" } var lifeCycle: Lifecycle by Delegates.notNull() var title: String? = null var mCurrentPath: String = "" private var disMissTime: Long = 0L private var toolBar: COUIToolbar? = null private var mTabTitle = arrayListOf( appContext.resources.getString(com.filemanager.common.R.string.total), appContext.resources.getString(com.filemanager.common.R.string.string_photos), appContext.resources.getString(com.filemanager.common.R.string.string_videos), appContext.resources.getString(com.filemanager.common.R.string.string_audio), appContext.resources.getString(com.filemanager.common.R.string.string_documents), appContext.resources.getString(com.filemanager.common.R.string.string_other) ) private val mTabTitles = intArrayOf( Constants.TAB_ALL, Constants.TAB_IMAGE, Constants.TAB_VIDEO, Constants.TAB_AUDIO, Constants.TAB_DOCUMENT, Constants.TAB_OTHER ) private var mAddFileDialogInterface: AddFileDialogInterface? = null private var mPages: ArrayList<AddFileListFragment> = ArrayList() private var mViewPager: RTLViewPager? = null private var mTabView: COUITabLayout? = null private var mViewPagerWrapper: ViewPagerWrapperForPC? = null private var addFileBtn: COUIButton? = null private var verticalButtonWrap: SingleButtonWrap? = null private var rootView: ViewGroup? = null private var addFilePanelViewModel: AddFilePanelViewModel? = null private var statisticsSelectTitleView: TextView? = null private var statisticsSelectBodyView: TextView? = null private var contentLayout: RelativeLayout? = null private var buttonDivider: View? = null private var statisticsArrowUpView: ImageView? = null private var statisticsRootView: ViewGroup? = null private var loadingController: LoadingController? = null private var mPosition: Int = 0 var limitCount: Int = 0 private val allFiles: MutableList<BaseFileBean> = mutableListOf() private val imageFiles: MutableList<BaseFileBean> = mutableListOf() private val videoFiles: MutableList<BaseFileBean> = mutableListOf() private val audioFiles: MutableList<BaseFileBean> = mutableListOf() private val docFiles: MutableList<BaseFileBean> = mutableListOf() private val otherFiles: MutableList<BaseFileBean> = mutableListOf() private val mSelectArrayByID: MutableSet<Long> = mutableSetOf() var addFileClickCallback: (selectData: List<AddFileBean>) -> Unit = {} var isExternalReference: Boolean = false private fun setPanelMaxHeight() { if (activity == null) return rootView?.layoutParams?.apply { if (UIConfigMonitor.isCurrentZoomWindowShow() && SdkUtils.isAtLeastR() && !isExternalReference) { val savedHeight: Int = arguments?.getInt(PANEL_MAX_HEIGHT) ?: 0 Log.d(TAG, "setPanelMaxHeight savedHeight = $savedHeight") if (savedHeight == 0) { // 处理浮窗 height = handleZoomWindowHeight(requireActivity(), height) arguments?.putInt(PANEL_MAX_HEIGHT, height) } else { height = savedHeight } Log.d(TAG, "setPanelMaxHeight height = $height") } else { val screenHeight = dp2px(requireActivity(), requireActivity().resources.configuration.screenHeightDp) val panelMaxHeight = COUIPanelMultiWindowUtils.getPanelMaxHeight(requireActivity(), requireActivity().resources.configuration) Log.d(TAG, "setPanelMaxHeight screenHeight:$screenHeight panelH:$panelMaxHeight height:$height") //当是分屏 if (requireActivity().isInMultiWindowMode) { if (StatusBarUtil.checkIsGestureNavMode(requireActivity())) { //全面屏手势导航 height = handleGestureNavModeHeight(requireActivity(), height) } else { // 底部导航栏 height = Math.min(screenHeight, panelMaxHeight) - requireActivity().resources.getDimensionPixelOffset( com.filemanager.common.R.dimen.dimen_40dp ) height = handleNavModeHeight(requireActivity(), height) } } rootView?.layoutParams = this } } } /** * 处理浮窗模式下的高度 */ private fun handleZoomWindowHeight(activity: Activity, height: Int): Int { var result = height val statusBarH = COUIPanelMultiWindowUtils.getStatusBarHeight(activity) val configuration = activity.resources.configuration val paddingBottom = COUIPanelMultiWindowUtils.getPanelMarginBottom(context, configuration) val rect = COUIPanelMultiWindowUtils.getCurrentWindowVisibleRect(activity) if (rect != null) { if (rect.top == 0) { Log.d(TAG, "handleZoomWindowHeight: rect $rect top is invalid, reset") rect.top = activity.resources.getDimensionPixelOffset(com.filemanager.common.R.dimen.panel_min_top_margin) } if (rect.bottom == 0) { val windowH = KtViewUtils.getWindowSize(activity).y rect.bottom = windowH Log.d(TAG, "handleZoomWindowHeight: rect $rect bottom is invalid, reset $windowH") } result = (rect.bottom - rect.top) - paddingBottom - statusBarH Log.d(TAG, "handleZoomWindowHeight: height $result = ${rect.bottom}-${rect.top}-$paddingBottom-$statusBarH") } return result } /** * 处理底部导航栏导航时的高度 */ private fun handleNavModeHeight(it: Activity, height: Int): Int { val navBarHeight = KtViewUtils.getSoftNavigationBarSize(it) var result = height when { ModelUtils.isTablet() -> { //平板竖屏分屏时 if (UIConfigMonitor.instance.isDevicePortrait(it)) { result = height - navBarHeight Log.d(TAG, "handleNavMode pad portrait height:$result") } } UIConfigMonitor.instance.isFoldable(it) -> { // 折叠屏 result = height - navBarHeight Log.d(TAG, "handleNavMode fold height:$result") } else -> { //手机且分屏处于下屏 if (!COUIPanelMultiWindowUtils.isDisplayInUpperWindow(it)) { result = height - navBarHeight Log.d(TAG, "handleNavMode phone lower split screen height:$result") } } } return result } /** * 处理全面屏手势导航时的高度 */ @VisibleForTesting fun handleGestureNavModeHeight(activity: Activity, height: Int): Int { if (COUIPanelMultiWindowUtils.isDisplayInUpperWindow(activity)) { // 上分屏,不用处理 return height } // 处于下分屏,并且显示了手势指示条 if (StatusBarUtil.checkShowGestureNavBar(activity)) { val result = height - activity.resources.getDimensionPixelOffset(com.filemanager.common.R.dimen.dimen_16dp) Log.d(TAG, "handleGestureNavMode lower split screen with show gesture nvaBar height:$result") return result } return height } override fun onDestroy() { Log.d(TAG, "onDestroy") super.onDestroy() verticalButtonWrap?.release() clearDataList() addFilePanelViewModel?.onDestroy() } override fun initView(panelView: View?) { activity?.let { activity -> LayoutInflater.from(activity).inflate(getLayoutResId(), null, false)?.let { (contentView as? ViewGroup)?.addView(it) initContentView(it) initViewModel(activity) startObserver() initData() } } } private fun getLayoutResId(): Int { return R.layout.add_file_panel_dialog } private fun initViewModel(act: FragmentActivity) { addFilePanelViewModel = ViewModelProvider(act)[AddFilePanelViewModel::class.java] } private fun startObserver() { addFilePanelViewModel?.mAllFiles?.observe(this) { it ?: return@observe showLoadingView(false) setViewPagerData(it) } addFilePanelViewModel?.mAllSelectFiles?.observe(this) { it ?: return@observe updateStatisticsSelectView(it) } } fun notifyUpdate() { mSelectArrayByID.clear() addFilePanelViewModel?.mAllSelectFiles?.value?.forEach { bean -> if (bean.isSelected) { bean.mFileID?.let { mSelectArrayByID.add(it) } } } getCurrentFragment()?.apply { setSelectedData(mSelectArrayByID) notifyUpdate() } } private fun initContentView(view: View) { Log.d(TAG, "initContentView") hideDragView() rootView = view.findViewById(R.id.dialog_layout) toolBar = view.findViewById(R.id.toolbar) mTabView = view.findViewById<COUITabLayout?>(R.id.tab_layout) mViewPager = view.findViewById(R.id.viewPager) mViewPagerWrapper = view.findViewById<ViewPagerWrapperForPC?>(R.id.view_pager_wrapper).apply { notifyMainViewPager = object : ((Boolean) -> Unit) { override fun invoke(enable: Boolean) { activity?.let { val mainAction = Injector.injectFactory<IMain>() mainAction?.setViewPagerScrollEnabled(it, enable) } } } } addFileBtn = view.findViewById<COUIButton?>(R.id.btn_add_file).apply { verticalButtonWrap = SingleButtonWrap(this, SingleButtonWrap.Type.Small) setOnClickListener { Log.d(TAG, "addFileBtn click. select:${addFilePanelViewModel?.mAllSelectFiles?.value?.size}") val selectList = addFilePanelViewModel?.mAllSelectFiles?.value selectList?.let { addFileClickCallback.invoke(it) } } } contentLayout = view.findViewById(R.id.content_layout) buttonDivider = view.findViewById(R.id.button_divider) statisticsSelectTitleView = view.findViewById<TextView?>(R.id.select_title_content) statisticsSelectBodyView = view.findViewById<TextView?>(R.id.select_body_content) statisticsArrowUpView = view.findViewById(R.id.select_arraw_up) statisticsRootView = view.findViewById<ViewGroup?>(R.id.select_root_view).apply { setOnClickListener { if (Utils.isQuickClick()) { Log.w(TAG, "click too fast, try later") return@setOnClickListener } addFilePanelViewModel?.mAllSelectFiles?.value?.let { mAddFileDialogInterface?.replaceSelectedPanelFragment(it) } } } setPanelMaxHeight() } private fun initData() { initToolBar() resetStatisticsView() val fragments = childFragmentManager.fragments for (i in mTabTitles.indices) { initFragment(i, fragments) } initViewPager() if (PrivacyPolicyController.hasAgreePrivacy()) { loadData() } else { PrivacyPolicyController.bindPrivacyPolicyListener(this) } } private fun loadData() { Log.d(TAG, "loadData") showLoadingView(true) // 加载数据 activity?.let { addFilePanelViewModel?.loadAllFiles(it) } } private fun resetStatisticsView() { addFileBtn?.isEnabled = false statisticsSelectTitleView?.apply { visibility = View.VISIBLE text = appContext.resources.getString(com.filemanager.common.R.string.not_selected_file) } statisticsSelectBodyView?.apply { visibility = View.GONE text = "" } statisticsArrowUpView?.apply { visibility = View.GONE } statisticsRootView?.apply { isClickable = false } } private fun initToolBar() { toolBar?.apply { visibility = View.VISIBLE title = appContext.resources.getString(com.filemanager.common.R.string.encryption_file_select_title) isTitleCenterStyle = true inflateMenu(R.menu.add_file_panel_dialog_menu_bar) menu.findItem(R.id.cancel).setOnMenuItemClickListener { mAddFileDialogInterface?.dismissAddFileDialog() true } } if ((mTabView != null) && (mViewPager != null)) { mTabView?.let { it.setupWithViewPager(mViewPager, false) it.addOnTabSelectedListener(this) it.isUpdateindicatorposition = true } } } fun setAddFileDialogInterface(addFileDialog: AddFileDialogInterface) { mAddFileDialogInterface = addFileDialog } private fun initViewPager() { mViewPager?.let { it.offscreenPageLimit = mTabTitles.size it.adapter = ViewPagerFragmentStateAdapter(this) it.currentItem = 0 it.overScrollMode = View.OVER_SCROLL_NEVER } } private fun initFragment(position: Int, fragments: List<Fragment>): Fragment { Log.d(TAG, "initFragment") var fragment = if (fragments.isEmpty()) null else fragments[position] if (fragment == null) { fragment = AddFileListFragment() fragment.isExternalReference = isExternalReference fragment.lifeCycle = lifeCycle fragment.mOnItemSelectCallback = { _, fileID -> mSelectArrayByID.add(fileID) addFilePanelViewModel?.updateAllSelectFiles(mSelectArrayByID) } fragment.mOnItemUnSelectCallback = { _, fileID -> mSelectArrayByID.remove(fileID) addFilePanelViewModel?.updateAllSelectFiles(mSelectArrayByID) } fragment.mFileEmptyCallback = { isShowEmpty -> handleFileEmptyView(isShowEmpty) } fragment.mCurrentPath = mCurrentPath fragment.limitCount = limitCount } if (fragment is AddFileListFragment) { mPages.add(fragment) } return fragment } private fun handleFileEmptyView(isShowEmptyView: Boolean) { if (isShowEmptyView) { showLoadingView(false) buttonDivider?.alpha = 0F } else { buttonDivider?.alpha = 1F } } private fun showLoadingView(isShow: Boolean) { if (isShow) { Log.d(TAG, "showLoadingView disMissTime $disMissTime") activity?.let { loadingController = LoadingController(it, this) //如果异常loadingView刚刚调用,就不调用显示loadingView,防止loadingView一直显示 Log.d(TAG, "showLoadingView getLoadingShowStartTime ${loadingController?.getLoadingShowStartTime()}") if (SystemClock.elapsedRealtime() - disMissTime >= DISMISS_TIME_GAP || loadingController?.getLoadingShowStartTime() == 0L) { loadingController?.showLoading(contentLayout) } } } else { Log.d(TAG, "showLoadingView dismissLoading") loadingController?.dismissLoading() disMissTime = SystemClock.elapsedRealtime() } } override fun onShow(isShowOnFirstPanel: Boolean?) { super.onShow(isShowOnFirstPanel) ((parentFragment as? COUIBottomSheetDialogFragment)?.dialog as? COUIBottomSheetDialog) ?.setPanelBackgroundTintColor(COUIContextUtil.getAttrColor(context, com.support.appcompat.R.attr.couiColorBackgroundElevatedWithCard)) } private fun clearDataList() { allFiles.clear() imageFiles.clear() videoFiles.clear() audioFiles.clear() docFiles.clear() otherFiles.clear() mSelectArrayByID.clear() } private fun setViewPagerData(data: MutableList<AddFileBean>) { Log.d(TAG, "setViewPagerData") clearDataList() allFiles.addAll(data) val documentExtensionType = Injector.injectFactory<IDocumentExtensionType>() data.forEach { file -> val localType = file.mLocalType if (MimeTypeHelper.isImageType(localType)) { imageFiles.add(file) } else if (MimeTypeHelper.isVideoType(localType)) { videoFiles.add(file) } else if (MimeTypeHelper.isAudioType(localType)) { audioFiles.add(file) } else if ((MimeTypeHelper.isDocType(localType) || MimeTypeHelper.isOtherDocType(localType)) && documentExtensionType?.isCategoryDocSupportType(file) == true ) { //isCategoryDocSupportType确保面板上文档分类显示的内容和文管文档分类一致(部分未知格式后缀会识解析TXT类型) docFiles.add(file) } else { otherFiles.add(file) } } updateData(mTabTitles[mPosition]) } private fun updateStatisticsSelectView(data: MutableList<AddFileBean>) { if (data.size <= 0) { Log.d(TAG, "unselect file") resetStatisticsView() return } addFileBtn?.isEnabled = true statisticsSelectTitleView?.apply { visibility = View.VISIBLE text = appContext.resources.getQuantityString( com.filemanager.common.R.plurals.mark_selected_items_new, data.size, data.size ) } statisticsSelectBodyView?.apply { visibility = View.VISIBLE val size: Long = data.sumOf { it.mSize } val totalSize: String = updateSizeFormat(size) text = appContext.resources.getString(com.filemanager.common.R.string.selected_size, totalSize) } statisticsArrowUpView?.apply { visibility = View.VISIBLE } statisticsRootView?.apply { isClickable = true } } @SuppressLint("DefaultLocale") fun updateSizeFormat(size: Long): String { return if (size < NUM) { size.toString() + "B" } else if (size < NUM * NUM) { String.format("%.1f", (size / DECIMAL_NUM)) + " KB" } else if (size < NUM * NUM * NUM) { String.format("%.1f", (size / NUM / DECIMAL_NUM)) + " MB" } else { String.format("%.1f", (size / NUM / NUM / DECIMAL_NUM)) + " GB" } } private fun updateData(fragmentType: Int) { val fragment = getCurrentFragment() fragment?.mFragmentType = fragmentType when (fragmentType) { Constants.TAB_ALL -> fragment?.setData(allFiles) Constants.TAB_IMAGE -> fragment?.setData(imageFiles) Constants.TAB_VIDEO -> fragment?.setData(videoFiles) Constants.TAB_AUDIO -> fragment?.setData(audioFiles) Constants.TAB_DOCUMENT -> fragment?.setData(docFiles) Constants.TAB_OTHER -> fragment?.setData(otherFiles) } fragment?.setSelectedData(mSelectArrayByID) Log.d( TAG, "allFiles=${allFiles.size}, imageFiles=${imageFiles.size}, videoFiles=${videoFiles.size}, " + "audioFiles=${audioFiles.size}, docFiles=${docFiles.size}, otherFiles=${otherFiles.size}" ) } override fun onTabSelected(tab: COUITab?) { Log.d(TAG, "onTabSelected tab.postion=${tab?.position}") tab?.let { mPosition = it.position if (loadingController?.isShowing() != true) { updateData(mTabTitles[mPosition]) } } } override fun onTabUnselected(p0: COUITab?) {} override fun onTabReselected(p0: COUITab?) {} private fun getCurrentFragment(): AddFileListFragment? { return if (mPosition < mPages.size) { mPages[mPosition] } else { null } } inner class ViewPagerFragmentStateAdapter(fragment: Fragment) : BaseFragmentAdapter(fragment) { override fun getItemCount(): Int { return mTabTitle.size } override fun createFragment(position: Int): Fragment { return mPages[position] } override fun getPageTitle(position: Int): CharSequence { return mTabTitle[position] } } override fun onAgreeResult(agree: Boolean, noLongerRemind: Boolean) { loadData() } } interface AddFileDialogInterface { fun dismissAddFileDialog() fun replaceSelectedPanelFragment(selectData: MutableList<AddFileBean>) }这是对应的kotlin代码,怎么处理
07-29
<think> 我们正在分析用户的问题:在TableRow中添加多个TextView,只有前两个能正常显示的原因。 根据提供的代码片段: <TableRow android:layout_width="wrap_content"> <TextView android:layout_width="wrap_content" android:text="编号" /> <TextView android:layout_width="wrap_content" android:text="prn" /> <TextView android:layout_width="wrap_content" android:text="仰角" /> <TextView android:layout_width="wrap_content" android:text="方位角" /> <TextView android:layout_width="wrap_content" android:text="CNR" /> </TableRow> 结合之前的回答和引用,原因主要是: 1. TableRow的宽度默认是match_parent(根据引用[1]),但这里用户设置了wrap_content,这可能导致TableRow宽度不足以容纳所有列。 2. 每个TextView的宽度都是wrap_content,当列数较多时,超过屏幕宽度的部分将无法显示(被压缩或不可见)。 具体解释: 根据引用[1]:TableRow的宽度自动填满父容器(应该是match_parent),但用户在此处设置了wrap_content,这是不符合TableRow默认行为的(可能引起问题)。不过,即使TableRow宽度为match_parent,由于所有TextView都是wrap_content,当总宽度超过屏幕时,后面的列会被挤压或不可见。 为什么只有前两个显示? 因为每个TextView的wrap_content会使每个列宽度为文本宽度,当屏幕宽度只能容纳两个文本时(比如“编号”和“prn”),后面的列就会被挤到屏幕外。 解决方法: 使用权重(layout_weight)来分配宽度,并设置宽度为0dp(如引用[2]所示)。或者使用TableLayout的属性来设置列的可收缩和可伸展。 另外,引用[3]中提到使用layout_span可以跨列,但这里不适用,因为我们需要的是每列都显示。 引用[4]提到动态添加时的LayoutParams,但这里是静态布局。 因此,解决方案是修改布局代码,使用权重分配宽度。 修改后的代码示例: <TableRow android:layout_width="match_parent" <!-- 改为match_parent,或者不设置(默认就是match_parent) --> android:layout_height="wrap_content"> <!-- 每个TextView设置layout_width为0dp,并分配权重 --> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="编号" /> <!-- 其余TextView类似 --> ... </TableRow> 注意:权重和(即每个列分配相同的权重)应该一致,这里每列都设置为1,表示均分宽度。 另外,可以在TableLayout中设置属性来支持收缩和伸展: <TableLayout android:shrinkColumns="*" <!-- 所有列都可收缩 --> android:stretchColumns="*"> <!-- 所有列都可伸展 --> 这样即使不设置权重,也可以让所有列适应屏幕(但权重方式更精确控制均分)。 所以,根本原因是列宽超过屏幕宽度,而默认情况下超出部分被挤压或不可见。通过权重分配或设置TableLayout的属性可以解决。 </think> 您遇到的问题是由于**列宽计算规则**导致的,根本原因是没有正确分配列宽权重。根据引用[1]和引用[2]的关键信息,以下是具体分析和解决方案: ### 原因分析 1. **列宽溢出屏幕(核心问题)** 当所有`TextView`都使用`wrap_content`时: $$ \text{总宽度} = \sum_{i=1}^{5} \text{文本宽度}_i > \text{屏幕宽度} $$ 超出部分会被压缩(引用[1]),导致第3列开始的文本宽度被计算为: $$ \text{实际宽度} = \max\left(0, \ \text{剩余屏幕宽度} \right) $$ 因此只有前两列可见(引用[2]) 2. **未使用权重分配机制** `TableRow`默认按内容宽度分配空间,未设置`layout_weight`时: ```xml <!-- 错误写法:所有列竞争空间 --> <TextView android:layout_width="wrap_content" .../> ``` ### 解决方案(代码修正) ```xml <TableLayout android:shrinkColumns="*" <!-- 允许所有列收缩 --> android:stretchColumns="*"> <!-- 允许所有列伸展 --> <TableRow> <!-- 每列设置权重分配 --> <TextView android:layout_width="0dp" <!-- 关键:宽度设为0 --> android:layout_height="wrap_content" android:layout_weight="1" <!-- 权重均分 --> android:text="编号" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="prn" /> <!-- 重复同样设置 --> <TextView ... android:text="仰角" /> <TextView ... android:text="方位角" /> <TextView ... android:text="CNR" /> </TableRow> </TableLayout> ``` ### 效果验证 修正后每列宽度计算公式: $$ \text{单列宽度} = \frac{\text{屏幕宽度}}{\text{列数}} = \frac{\text{屏幕宽度}}{5} $$ 所有列将等宽显示,避免溢出问题(引用[2])。 --- ### 进阶技巧(非均等列宽) 若需自定义列宽比例,调整权重值: ```xml <TextView android:layout_weight="2" <!-- 此列占2份宽度 --> .../> <TextView android:layout_weight="1" <!-- 此列占1份宽度 --> .../> ``` 此时宽度比值为 $2:1$(引用[2]) > **注意**:动态添加列时(引用[4]),需同步设置`LayoutParams`: > ```java > TableRow.LayoutParams params = new TableRow.LayoutParams( > 0, > TableRow.LayoutParams.WRAP_CONTENT, > 1.0f // 权重值 > ); > textView.setLayoutParams(params); > ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

唐诺

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

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

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

打赏作者

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

抵扣说明:

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

余额充值