headerView跟随 cell一起滚动 及headerView 作为表头背景的实现

本文介绍如何实现UITableView中表头背景图片随拖动显示更多内容,并保持headerView与cell同步滚动的效果,适用于iOS应用开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UITableView 的 表头背景 和 headerView跟随 cell一起滚动

这是我在做一个项目时遇到的问题:怎样像新浪微博或者QQ空间里的:“个人空间”那样,在表格最上方有个背景图片(把背景放在表头)?向下拖动时能显示更多的图片内容?向上拖时,表格的UITableViewStyle不用改为group,headerView也能跟随一起滚动?

1.向下拖动时能显示更多的图片内容?

可以这样:设置UIEdgeInsetsMake(top, left, bottom, right);
,比如UIEdgeInsetsMake(-100,0,0,0)。效果是:表格的最上方插入一段高-100大小的空余,很明显-100就是表格显示时从表格内容高度100的地方开始显示,高度比100小的被隐藏了,只有向下拖动才能看到。(解决)


2.向上拖时,表格的UITableViewStyle不用改为group,headerView也能跟随cell一起滚动?

这个很简单,但是花了哥哥不少时间。(主要是各种“百” 、各种“度”,但是都没满意的做法,可能有经验的早就知道了。不过没分享出来,至少我找了好久都没找到!!)

只要:设section==0时,cell的数量为0 OK了,问题解决了。


链接

http://blog.youkuaiyun.com/tangaowen/article/details/6452314

他的第三个方法是什么意思,我没弄懂。

有个不满意地方:新浪微博的背景能拉伸,该怎么搞还得研究研究,如果你有好方法大笑



下面是代码:头文件定义一个UITableView的子类,图片自己搞

#import "ViewController.h"


@interfaceViewController ()

@end

@implementation ViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

   self = [superinitWithNibName:nibNameOrNilbundle:nibBundleOrNil];

   if (self) {

        // Custom initialization

    }

    returnself;

}

- (void)viewDidLoad

{

    [superviewDidLoad];

    self.view.backgroundColor=[UIColorgrayColor];

    _table=[[UITableViewalloc]initWithFrame:CGRectMake(0,10,320, 480)style:UITableViewStylePlain];

    _table.backgroundView=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"2.1.png"]];

   _table.contentInset=UIEdgeInsetsMake(-100,0,0, 0);

    _table.delegate=self;

    _table.dataSource=self;

    [self.viewaddSubview:_table];

}

#pragma mark - Table view data source


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

{

   return3;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

   if (section==0) {

       return0;

    }

   return5;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

   staticNSString *CellIdentifier =@"Cell";

   UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

   if (cell==nil) {

        cell=[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:CellIdentifier];

    }

    cell.textLabel.text=@"fdsafe";

    cell.backgroundView=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"2.1.png"]];

    

   return cell;

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

   return111;

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{

   if (section==0) {

       return200;

    }

   return0;

}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

    

    UIImageView *img=[[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"backGround.png"]];

    img.frame=CGRectMake(10,0,320, 400);

   return img;

}

- (void)didReceiveMemoryWarning

{

    [superdidReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end


private void addTableRow(TableLayout table, Object[] rowData) { TableRow row = new TableRow(requireContext()); // 设置行布局参数(正确方式) TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT ); row.setLayoutParams(rowParams); // 设置最小行高(单位:dp) int minRowHeight = dpToPx(36); row.setMinimumHeight(minRowHeight); for (Object data : rowData) { TextView textView = new TextView(requireContext()); textView.setText(String.valueOf(data)); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); // 设置单元格内边距 int padding = dpToPx(8); textView.setPadding(padding, padding/2, padding, padding/2); // 设置单行显示 textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); // 创建列布局参数(正确方式) TableRow.LayoutParams colParams = new TableRow.LayoutParams( 0, // 宽度将由权重控制 TableRow.LayoutParams.MATCH_PARENT ); // 设置权重和最小宽度 colParams.weight = 1; textView.setLayoutParams(colParams); // 设置文本视图的最小宽度(这才是正确的属性) textView.setMinWidth(dpToPx(120)); // 设置最小列宽 row.addView(textView); } table.addView(row); } // 动态添加表头 private void addTableHeader(TableLayout table) { TableRow headerRow = new TableRow(requireContext()); headerRow.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.purple_500)); TableLayout.LayoutParams headerParams = new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT ); headerRow.setLayoutParams(headerParams); String[] headers = {"订单号", "产品编号", "产品数量", "组件名", "板材信息", "板材/组件", "订购数量"}; for (String header : headers) { TextView headerView = new TextView(requireContext()); headerView.setText(header); headerView.setTextColor(Color.WHITE); headerView.setTypeface(null, Typeface.BOLD); headerView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); int padding = dpToPx(8); headerView.setPadding(padding, padding, padding, padding); // 设置列布局参数 TableRow.LayoutParams colParams = new TableRow.LayoutParams( 0, TableRow.LayoutParams.MATCH_PARENT ); colParams.weight = 1; headerView.setLayoutParams(colParams); // 设置表头列的最小宽度 headerView.setMinWidth(dpToPx(120)); headerRow.addView(headerView); } table.addView(headerRow); } // DP转PX工具方法 private int dpToPx(int dp) { return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() ); }<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 水平滚动容器(关键:宽度设为match_parent) --> <HorizontalScrollView android:id="@+id/scroll_horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:scrollbars="horizontal"> <!-- 表格容器(高度为wrap_content,宽度设为可无限扩展) --> <TableLayout android:id="@+id/orderTable" android:layout_width="wrap_content" android:layout_height="wrap_content" android:stretchColumns="*" android:shrinkColumns="*" android:paddingEnd="16dp" android:minWidth="1000dp"> <!-- 设置最小宽度防止初始压缩 --> <!-- 表格标题行(已移除原始代码中的标题行,将在Java中动态添加) --> </TableLayout> </HorizontalScrollView> <!-- 垂直滚动指示器 --> <View android:layout_width="4dp" android:layout_height="match_parent" android:layout_gravity="right" android:background="#80000000" android:visibility="invisible" android:id="@+id/vertical_scroll_indicator"/> </FrameLayout> textView.setSingleLine(true);单行不忽略,动态调整长度,总长可以延伸
06-07
package com.example.kucun2.ui.dingdan;//package com.example.kucun2; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; import com.example.kucun2.R; import com.example.kucun2.View.HorizontalScrollTextView; import com.example.kucun2.entity.Bancai; import com.example.kucun2.entity.Chanpin; import com.example.kucun2.entity.Chanpin_Zujian; import com.example.kucun2.entity.Dingdan; import com.example.kucun2.entity.Dingdan_Bancai; import com.example.kucun2.entity.Dingdan_Chanpin; import com.example.kucun2.entity.data.Data; import com.example.kucun2.entity.Zujian; import java.util.List; public class OrderDisplayFragment extends Fragment { private TableLayout table; private HorizontalScrollView horizontalScrollView; private ValueAnimator scrollIndicatorAnimator; private boolean isIndicatorVisible = false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_order_display, container, false); table = view.findViewById(R.id.orderTable); horizontalScrollView = view.findViewById(R.id.horizontalScrollContainer); View scrollIndicator = view.findViewById(R.id.scroll_indicator); // 添加表头 addTableHeader(table); // 填充表格数据 fillTableData(); // 添加滚动监听 horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(() -> { int maxScroll = horizontalScrollView.getChildAt(0).getWidth() - horizontalScrollView.getWidth(); int currentScroll = horizontalScrollView.getScrollX(); if (currentScroll > 0 && maxScroll > 0) { if (!isIndicatorVisible) { showScrollIndicator(); } // 更新滚动指示器位置 updateScrollIndicatorPosition(currentScroll, maxScroll); } else { hideScrollIndicator(); } }); return view; } private void fillTableData() { List<Dingdan> orders = Data.dingdans; List<Dingdan_Chanpin> orderProducts = Data.dingdanChanpins; List<Dingdan_Bancai> orderMaterials = Data.dingdanBancais; for (Dingdan order : orders) { for (Dingdan_Chanpin orderProduct : orderProducts) { if (orderProduct.getDingdan().getId().equals(order.getId())) { Chanpin product = orderProduct.getChanpin(); for (Chanpin_Zujian component : product.getZujians()) { for (Dingdan_Bancai material : orderMaterials) { if (material.getZujian() != null && material.getZujian().getId().equals(component.getId())) { addTableRow(createRowData( order, product, component, material )); } } } } } } } private void addTableRow(Object[] rowData) { TableRow row = new TableRow(requireContext()); TableLayout.LayoutParams rowParams = new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT ); row.setLayoutParams(rowParams); row.setMinimumHeight(dpToPx(36)); for (Object data : rowData) { HorizontalScrollTextView textView = new HorizontalScrollTextView(requireContext()); textView.setText(String.valueOf(data)); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); int padding = dpToPx(8); textView.setPadding(padding, padding / 2, padding, padding / 2); textView.setMinWidth(dpToPx(50)); TableRow.LayoutParams colParams=null; // 设置背景边框 textView.setBackgroundResource(R.drawable.cell_border); if ( data.toString().length() > 10){ colParams = new TableRow.LayoutParams( 0, // 宽度将由权重控制 TableRow.LayoutParams.MATCH_PARENT, 2.0f ); colParams.weight = 1; }else{ colParams = new TableRow.LayoutParams( 0, // 宽度将由权重控制 TableRow.LayoutParams.MATCH_PARENT, 1.0f ); colParams.weight = 1; } textView.setLayoutParams(colParams); row.addView(textView); } table.addView(row); } // 动态添加表头 (使用自定义TextView) private void addTableHeader(TableLayout table) { TableRow headerRow = new TableRow(requireContext()); headerRow.setLayoutParams(new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT )); // 设置行背景颜色 headerRow.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.purple_500)); // 定义表头 String[] headers = getResources().getStringArray(R.array.table_headers); float[] weights = {1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 1.0f, 1.0f}; // 列宽优先级数组(板材信息列优先) boolean[] priority = {false, false, false, false, true, false, false}; for (int i = 0; i < headers.length; i++) { HorizontalScrollTextView headerView = new HorizontalScrollTextView(requireContext()); headerView.setText(headers[i]); headerView.setTextColor(Color.WHITE); headerView.setTypeface(null, Typeface.BOLD); headerView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); headerView.setPadding(dpToPx(8), dpToPx(8), dpToPx(8), dpToPx(8)); // 为优先级高的列设置最小宽度 if (priority[i]) { headerView.setMinWidth(dpToPx(100)); headerView.weight=2; } // 设置布局参数 TableRow.LayoutParams colParams = new TableRow.LayoutParams( priority[i] ? TableRow.LayoutParams.WRAP_CONTENT : 0, TableRow.LayoutParams.MATCH_PARENT, priority[i] ? 0 : weights[i] // 优先级列不使用权重 ); headerView.setLayoutParams(colParams); headerRow.addView(headerView); } table.addView(headerRow); } private void showScrollIndicator() { isIndicatorVisible = true; View indicator = getView().findViewById(R.id.scroll_indicator); if (scrollIndicatorAnimator != null && scrollIndicatorAnimator.isRunning()) { scrollIndicatorAnimator.cancel(); } indicator.setVisibility(View.VISIBLE); indicator.setAlpha(0f); scrollIndicatorAnimator = ObjectAnimator.ofFloat(indicator, "alpha", 0f, 0.8f); scrollIndicatorAnimator.setDuration(300); scrollIndicatorAnimator.start(); } private void hideScrollIndicator() { isIndicatorVisible = false; View indicator = getView().findViewById(R.id.scroll_indicator); if (scrollIndicatorAnimator != null && scrollIndicatorAnimator.isRunning()) { scrollIndicatorAnimator.cancel(); } scrollIndicatorAnimator = ObjectAnimator.ofFloat(indicator, "alpha", indicator.getAlpha(), 0f); scrollIndicatorAnimator.setDuration(300); scrollIndicatorAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { indicator.setVisibility(View.INVISIBLE); } }); scrollIndicatorAnimator.start(); } private void updateScrollIndicatorPosition(int currentScroll, int maxScroll) { View indicator = getView().findViewById(R.id.scroll_indicator); FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) indicator.getLayoutParams(); // 计算指示器位置(0-100%) float percentage = (float) currentScroll / maxScroll; int maxMargin = getResources().getDisplayMetrics().widthPixels - indicator.getWidth(); // 设置右边距(控制位置) params.rightMargin = (int) (maxMargin * percentage); indicator.setLayoutParams(params); } // DP转PX工具方法 private int dpToPx(int dp) { return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() ); } /** * 数据组合 * @param order * @param product * @param component * @param material * @return */ private Object[] createRowData(Dingdan order, Chanpin product, Chanpin_Zujian component, Dingdan_Bancai material) { Bancai board = material.getBancai(); String boardInfo = board.TableText(); ; return new Object[] { order.getNumber(), // 订单号 product.getId(), // 产品编号 "1", // 产品数量 (根据需求调整) component.getZujian().getName(), // 组件名 boardInfo, // 板材信息 Math.round(component.getOne_several()), // 板材/组件 material.getShuliang() // 订购数量 }; } } colParams.weight = 1;管用 但标题错位
06-07
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值