精确定位及恢复ListView的位置

工作中遇到一个需求,对ListView某一项操作后刷新ListView,但是如果直接刷新,界面上ListView从第一列开始显示,用户体验不好,于是在网上搜了一些恢复LIstView滑动位置的方法。解决办法如下:


    List<HashMap<String, String>> list;
private int scrollPos;
    private int scrollTop;

    private void showLocalMp3() {
        
        list = new ArrayList<HashMap<String,String>>();
        LocalMP3Infor mp3Infor = null;
        HashMap<String, String> tempMap = null;
        
        for(int i=0; i<mp3InforList.size(); i++) {
            mp3Infor = (LocalMP3Infor)mp3InforList.get(i);
            tempMap = new HashMap<String, String>();
            tempMap.put("mp3_name", mp3Infor.getMp3_name());
            tempMap.put("mp3_size", mp3Infor.getMp3_size());
            list.add(tempMap);
        }
        
        SimpleAdapter simpleAdapter =
                new SimpleAdapter(this, list, R.layout.mp3list_resource, new String[] {"mp3_name", "mp3_size"}, new int[] {R.id.name, R.id.size});
        
        
        //给ListView设置监听器  【用来恢复ListView位置的】
        listView.setOnScrollListener(scrollListener);  
          
        setListAdapter(simpleAdapter);
        
        //在setListAdapter之后恢复ListView的位置
        listView.setSelectionFromTop(scrollPos, scrollTop);
        
    }
    
    private OnScrollListener scrollListener = new OnScrollListener() {  
           
        @Override  
        public void onScroll(AbsListView arg0, int arg1, int arg2, int arg3) {  
        }  

        @Override  
        public void onScrollStateChanged(AbsListView view, int scrollState) {  
            
                if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {  
                        // scrollPos记录当前可见的List顶端的一行的位置   
                       scrollPos = listView.getFirstVisiblePosition();   
                }  
                if (list != null) {   
                    
                      View v=listView .getChildAt(0);  
                      
                      scrollTop=(v==null)?0:v.getTop();  
                }    
 }  
}; 

 

参考:http://stackoverflow.com/questions/3014089/scroll-to-a-position-in-a-listview 


之前在网上搜到的,有另外两种方法
第一种:
在onScrollStateChanged里面 

scrolledX = listView.getScrollX(); 

 scrolledY = listView.getScrollY(); 

恢复时使用listView.scrollTo(scrolledX, scrolledY); 

 但是得到的scrolledY为0
第二种:
在onScrollStateChanged里面

position = listView.getFirstVisiblePosition(); 

用position记录显示在屏幕顶端的一个item,

恢复时使用listView.setSelection(position); 

但是这种方法不够精确
最后用setSelectionFromTop实现的

import os from PyQt5.QtWidgets import QListView, QApplication, QMainWindow, QStyledItemDelegate from PyQt5.uic import loadUi from PyQt5.QtCore import Qt, QSize, QFile, QPoint from PyQt5.QtGui import QPixmap, QPainter, QStandardItemModel, QStandardItem class BottomImageDelegate(QStyledItemDelegate): def __init__(self, aspect_ratio=16/9): super().__init__() self.aspect_ratio = aspect_ratio self.margin = 5 # 边距 def paint(self, painter, option, index): path = index.data(Qt.UserRole + 1) if not path or not QFile.exists(path): return # 获取动态尺寸 item_width = self.calculate_item_width(option.widget.width()) target_size = QSize(item_width, int(item_width / self.aspect_ratio)) # 加载并缩放图片 pixmap = QPixmap(path).scaled( target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation ) # 计算绘制位置 x = option.rect.x() + (option.rect.width() - pixmap.width()) // 2 y = option.rect.y() + (option.rect.height() - pixmap.height()) // 2 # 绘制背景和图片 painter.save() painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(QPoint(x, y), pixmap) painter.restore() def sizeHint(self, option, index): view_width = option.widget.width() return QSize(self.calculate_item_width(view_width), int(self.calculate_item_width(view_width) / self.aspect_ratio)) def calculate_item_width(self, view_width): # 根据视图宽度计算每项宽度(示例:至少显示4项) return max(200, view_width // 4 - 2*self.margin) class ListImageDelegate(QStyledItemDelegate): def __init__(self, aspect_ratio=16/9): super().__init__() self.aspect_ratio = aspect_ratio self.margin = 5 # 边距 def paint(self, painter, option, index): path = index.data(Qt.UserRole + 1) if not path or not QFile.exists(path): return # 获取动态尺寸 item_width = self.calculate_item_width(option.widget.width()) target_size = QSize(item_width, int(item_width / self.aspect_ratio)) # 加载并缩放图片 pixmap = QPixmap(path).scaled( target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation ) # 计算绘制位置 x = option.rect.x() + (option.rect.width() - pixmap.width()) // 2 y = option.rect.y() + (option.rect.height() - pixmap.height()) // 2 # 绘制背景和图片 painter.save() painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.drawPixmap(QPoint(x, y), pixmap) painter.restore() def sizeHint(self, option, index): view_width = option.widget.width() return QSize(self.calculate_item_width(view_width), int(self.calculate_item_width(view_width) / self.aspect_ratio)) def calculate_item_width(self, view_width): # 根据视图宽度计算每项宽度(示例:至少显示4项) return max(200, view_width // 4 - 2*self.margin) class MainWindow(QMainWindow): def __init__(self): super().__init__() loadUi("D:/Users/W20001405/Desktop/SWBU/AI_POSE/UI/show20.ui", self) # 初始化模型和委托 self.model = QStandardItemModel() self.delegate = ListImageDelegate() # 配置视图 self.listView_left.setModel(self.model) self.listView_left.setItemDelegate(self.delegate) # self.listView.setFlow(QListView.LeftToRight) # self.listView.setWrapping(False) # self.listView.setResizeMode(QListView.Adjust) # 加载示例图片 self.load_images(["D:/Users/W20001405/Desktop/SWBU/AI_POSE/1.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/2.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/1.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/2.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/1.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/2.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/1.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/2.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/1.png", "D:/Users/W20001405/Desktop/SWBU/AI_POSE/2.png"]) # 绑定窗口尺寸变化事件 self.resizeEvent = self.on_resize def load_images(self, paths): for path in paths: item = QStandardItem() item.setData(os.path.abspath(path), Qt.UserRole + 1) self.model.appendRow(item) def on_resize(self, event): # 触发委托尺寸重计算 self.delegate = ListImageDelegate() # 重新创建委托实例 self.listView_left.setItemDelegate(self.delegate) self.listView_left.updateGeometry() super().resizeEvent(event) if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec_() 给出详细注释
最新发布
05-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值