MFC实现子控件focus焦点上下移动父控件ListView和Gridview也跟着向上下移动

news2024/11/18 13:25:21

项目中要实现mfc功能,然后子控件焦点下移,LIstView和Gridview父控件不会下移,所以就有这个文章。废话不多说直接上代码。

MFCGridView.java

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.GridView;

import com.baidu.navisdk.ui.util.MFCUtil;

public class MFCGridView extends GridView {
    protected int lastPosition = -1;

    protected boolean mHasRegister = false;
    private final ViewTreeObserver.OnGlobalFocusChangeListener mFocusChangeListener =
            new ViewTreeObserver.OnGlobalFocusChangeListener() {
                @Override
                public void onGlobalFocusChanged(View oldFocus, View newFocus) {
                    if (!isInTouchMode()) {
                        refreshListViewScroll(oldFocus, newFocus);
                    }
                }
            };

    protected void refreshListViewScroll(View oldFocus, View newFocus) {
        if (getVisibility() != VISIBLE) {
            return;
        }
        if (newFocus == null) {
            return;
        }
        ViewParent convertView = getConvertView(newFocus);
        if (convertView == null) {
            return;
        }
        if (!(convertView instanceof View)) {
            return;
        }
        Object tagView = ((View) convertView).getTag();
        if (!(tagView instanceof IMFCHolder)) {
            if (lastPosition
                    != getAdapter().getCount() - 1) {
                smoothScrollToPositionFromTop(0, 0);
                lastPosition = -1;
            }
            return;
        }
        int focusedPosition = -1;
        View focusedChild =  getFocusedChild();
        if (focusedChild != null) {
            focusedPosition =  getPositionForView(focusedChild);
        }
        if (focusedPosition != lastPosition) {
            smoothScrollToPositionFromTop(focusedPosition, 50);
            lastPosition = focusedPosition;
        }
    }

    protected ViewParent getConvertView(View newFocus) {
        ViewParent lastView = null;
        ViewParent parent = newFocus.getParent();
        if (parent == this){
            return (ViewParent) newFocus;
        }
        while (parent != null) {
            if (parent == this) {
                return lastView;
            }
            lastView = parent;
            parent = parent.getParent();
        }
        return null;
    }

    public MFCGridView(Context context) {
        super(context);
        setFocusableInTouchMode(false);
    }

    public MFCGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setFocusableInTouchMode(false);
    }

    public MFCGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setFocusableInTouchMode(false);
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (MFCUtil.isMFCEnable()) {
            if (!mHasRegister) {
                getViewTreeObserver().addOnGlobalFocusChangeListener(mFocusChangeListener);
                mHasRegister = true;
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (MFCUtil.isMFCEnable()) {
            getViewTreeObserver().removeOnGlobalFocusChangeListener(mFocusChangeListener);
            mHasRegister = false;
        }
        clearDisappearingChildren();
    }
}

MFCGridView使用方法:xml中直接引用即可,无需其他操作

---------------------------------------------------------分割线---------------------------------------------------------

依赖类IMFCHolder.java
public interface IMFCHolder {
    int getPosition();
}

MFCListView.java

 import com.baidu.navisdk.ui.util.MFCUtil;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.ListView;

public class MFCListView extends ListView {
    protected boolean mHasRegister = false;
    protected int lastPosition = -1;
    private final ViewTreeObserver.OnGlobalFocusChangeListener mFocusChangeListener =
            new ViewTreeObserver.OnGlobalFocusChangeListener() {
                @Override
                public void onGlobalFocusChanged(View oldFocus, View newFocus) {
                    if (!isInTouchMode()) {
                        refreshListViewScroll(oldFocus, newFocus);
                    }
                }
            };

    protected void refreshListViewScroll(View oldFocus, View newFocus) {
        if (getVisibility() != VISIBLE) {
            return;
        }
        if (newFocus == null) {
            return;
        }
        ViewParent convertView = getConvertView(newFocus);
        if (convertView == null) {
            return;
        }
        if (!(convertView instanceof View)) {
            return;
        }
        Object tagView = ((View) convertView).getTag();
        if (!(tagView instanceof IMFCHolder)) {
            if (lastPosition
                    != getAdapter().getCount() - getHeaderViewsCount() - getFooterViewsCount()
                    - 1) {
                smoothScrollToPositionFromTop(0, 0);
                lastPosition = -1;
            }
            return;
        }
        IMFCHolder imfcHolder = (IMFCHolder) tagView;
        int position = imfcHolder.getPosition();
        if (position != lastPosition) {
            smoothScrollToPositionFromTop(position + getHeaderViewsCount(), 50);
            lastPosition = position;
        }
    }

    protected ViewParent getConvertView(View newFocus) {
        ViewParent lastView = null;
        ViewParent parent = newFocus.getParent();
        if (parent == this){
            return (ViewParent) newFocus;
        }
        while (parent != null) {
            if (parent == this) {
                return lastView;
            }
            lastView = parent;
            parent = parent.getParent();
        }
        return null;
    }

    public MFCListView(Context context) {
        super(context);
        setFocusableInTouchMode(false);
    }

    public MFCListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setFocusableInTouchMode(false);
    }

    public MFCListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setFocusableInTouchMode(false);
    }

    public MFCListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setFocusableInTouchMode(false);
    }

    @Override
    public View getFocusedChild() {
        return null;
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (MFCUtil.isMFCEnable()) {
            if (!mHasRegister) {
                getViewTreeObserver().addOnGlobalFocusChangeListener(mFocusChangeListener);
                mHasRegister = true;
            }
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (MFCUtil.isMFCEnable()) {
            getViewTreeObserver().removeOnGlobalFocusChangeListener(mFocusChangeListener);
            mHasRegister = false;
        }
        clearDisappearingChildren();
    }
}

依赖类MFCUtil.java

package com.baidu.navisdk.ui.util;

import android.app.Activity;

import com.baidu.naviauto.appcommon.AppLog;


import java.util.ArrayList;
import java.util.List;

public class MFCUtil {
    private static final String TAG = "MFCUtil";
    public static final List<String> REQUEST_CHECK_LIST_STRING = new ArrayList<>();

    public static boolean isMFCEnable() {

        return true;

    }

    /**
     *  返回false 不消费 调用者可以request
     *  返回true   消费  调用者不可以request
     * @param activity
     * @param classname
     * @return
     */
    public static boolean requestCheck(Activity activity, String classname) {
        if (activity == null) {
            return true;
        }
        if (!isMFCEnable()) {
            return true;
        }
        if (activity.getWindow().getDecorView().isInTouchMode()){
            return true;
        }
        checkRequestCheckList(activity);
        if (REQUEST_CHECK_LIST_STRING == null) {
            AppLog.e(TAG, "checkRequestCheckList  ==  " + classname);
            return false;
        }
        for (int i = 0; i < REQUEST_CHECK_LIST_STRING.size(); i++) {
            if (REQUEST_CHECK_LIST_STRING.get(i).equals(classname)) {
                AppLog.e(TAG, "false  ==  " + classname);
                return false;
            }
        }
        AppLog.e(TAG, "false finish  ==  " + classname);
        return false;
    }

    public static void checkRequestCheckList(Activity activity) {
        if (REQUEST_CHECK_LIST_STRING != null && REQUEST_CHECK_LIST_STRING.size() == 0) {

            REQUEST_CHECK_LIST_STRING.add("PowerNotification");
            REQUEST_CHECK_LIST_STRING.add("RestrictionTipsView");
            REQUEST_CHECK_LIST_STRING.add("RecommendTripTipsView");
            REQUEST_CHECK_LIST_STRING.add("PushPoiNaviNotificationView");
            REQUEST_CHECK_LIST_STRING.add("PushPoiNaviNotificationDialog");
            REQUEST_CHECK_LIST_STRING.add("NaviAutoActivity");
        }
    }

    public static void onDestory(){
        if (REQUEST_CHECK_LIST_STRING != null){
            REQUEST_CHECK_LIST_STRING.clear();
        }
    } 
}

MFCListView实际使用例子:

1.xml代码中使用MFCListView类代替

2.adapter中,核心代码如下:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_column, null);
            viewHolder = new ViewHolder();
            viewHolder.textView = convertView.findViewById(R.id.text);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.position = position;
        viewHolder.textView.setText(mProvinShotNameArr[position]);
 
        return convertView;
    }


public static class ViewHolder  implements IMFCHolder {
        TextView textView;
        int position;

        @Override
        public int getPosition() {
            return position;
        }
    }

实现成功:子控件焦点滑到中间,gridview父控件也跟着下滑了!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1799507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Cityengine】Cityengine生产带纹理的建筑模型导入UE4/UE5(下)

【Cityengine】Cityengine生产带纹理的建筑模型导入UE4/UE5&#xff08;下&#xff09; 一、导出数据&#xff08;2022中文版案例&#xff09;二、安装datasmith插件三、导入数据四、检查导入材质是否正常五、编辑替换材质六、安装模型编辑插件七、编辑替换建筑规则 一、导出数…

LLM的基础模型7:Positional Encoding

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

路径

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 用于定位一个文件或者目录的字符串被称为一个路径。在程序开发时&#xff0c;通常涉及两种路径&#xff0c;一种是相对路径&#xff0c;另一种是绝对…

关闭文件及使用with语句

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 1 关闭文件 打开文件后&#xff0c;需要及时关闭&#xff0c;以免对文件造成不必要的破坏。关闭文件可以使用文件对象的close()方法实现。close()方…

学习算法笔记(7.5)-贪心算法(股票售卖问题)

学到这里的大家应该都非常清楚贪心算法到底是怎么一回事了&#xff0c;说白了就是动态规划的一种特例&#xff0c;没有动态规划的使用范围广&#xff0c;但是效率却比动态规划效率高&#xff0c;贪心算法不考虑之前的情况&#xff0c;只考虑当前的最优选择以期达到最优的结果。…

通过血清拉曼光谱进行COVID-19的高效初步筛查

通过血清拉曼光谱进行COVID-19的高效初步筛查 原创 小王搬运工 时序课堂 2024-06-04 20:04 四川 论文地址&#xff1a;https://analyticalsciencejournals.onlinelibrary.wiley.com/doi/full/10.1002/jrs.6080 论文源码&#xff1a;无 期刊&#xff1a;JOURNAL OF RAMAN SPE…

数据挖掘实战-基于Catboost算法的艾滋病数据可视化与建模分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Qt 简易Word

Ui界面如下&#xff1a; 查找和替换界面&#xff1a; 具体代码&#xff1a; GitHub : 简易Word Gitee : 简易Word

package.json中resolutions的使用场景

文章目录 用途配置示例使用方法注意事项和peerDependencies有什么不同peerDependenciesresolutions 总结 ✍创作者&#xff1a;全栈弄潮儿 &#x1f3e1; 个人主页&#xff1a; 全栈弄潮儿的个人主页 &#x1f3d9;️ 个人社区&#xff0c;欢迎你的加入&#xff1a;全栈弄潮儿的…

九大微服务监控工具详解

Prometheus Prometheus 是一个开源的系统监控、和报警工具包&#xff0c;Prometheus 被设计用来监控“微服务架构”。 主要解决&#xff1a; 监控和告警&#xff1a;Prometheus 可以对系统、和应用程序进行实时监控&#xff0c;并在出现问题时发送告警&#xff1b;数据收集和…

构建体育直播平台源码:深度解析数据分析模块的核心展示内容

在现代的体育直播平台中&#xff0c;数据分析展示已经成为不可或缺的一部分。如下参考借助“东莞梦幻网络科技”提供的体育直播源码&#xff0c;打造的平台&#xff0c;并通过表格形式为用户列出以下数据分析内容&#xff1a; 1、积分排名&#xff1a;反映了各支队伍在赛季中的…

【全开源】JAVA打车小程序APP打车顺风车滴滴车跑腿源码微信小程序打车源码

&#xff1a;构建便捷出行新体验 一、引言&#xff1a;探索打车系统小程序源码的重要性 在数字化快速发展的今天&#xff0c;打车系统小程序已成为我们日常生活中不可或缺的一部分。它以其便捷、高效的特点&#xff0c;极大地改变了我们的出行方式。而背后的关键&#xff0c;…

Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端

Android14 WMS-窗口添加流程(一)-Client端-CSDN博客 Android14 WMS-窗口添加流程(二)-Server端-CSDN博客 经过上述两个流程后&#xff0c;窗口的信息都已经传入了WMS端。 1. ViewRootImpl#setView 在窗口添加流程(一)中&#xff0c;有这个方法&#xff1a; http://aospxref…

Ubuntu22.04 下 pybind11 搭建,示例

Pybind11 是一个轻量级的库&#xff0c;用于在 C 中创建 Python 绑定。Ubuntu22下安装pybind11步骤如下&#xff1a; 1. 安装 pybind11 1.1 pip 命令安装 pip3 install pybind11 1.2 源代码安装 安装依赖库&#xff1a; sudo pip install -i https://pypi.tuna.tsinghua.e…

要想数据形成好的数据集,必须数据治理(目的之一是防止大模型产生灰色数据等),用于炼丹(训练数据私有化模型)的数据才是好数据

数据治理&#xff1a;必要性、实施方法及挑战 引言 在当今数字化时代&#xff0c;数据已经成为企业最重要的资产之一。随着数据量的爆炸性增长&#xff0c;如何有效地管理和利用数据成为企业面临的重大挑战。数据治理&#xff08;Data Governance&#xff09;作为一种系统化的…

排序数组 ---- 分治-归并

题目链接 题目: 分析: 用这道题来回顾一下归并排序的思想找到中间结点, 将数组分成两半, 运用递归的思想, 继续对一半进行分半, 分到最后剩一个元素, 再将左右数组合并, 合并两个有序数组, 是先分解, 再合并的过程在合并两个有序数组时, 需要一个额外的数组来记录, 为了避免每…

【RabbitMQ基础】-RabbitMQ:初识MQ[1]

简介 RabbitMQ &#xff08;高性能的异步通讯组件&#xff09; RabbitMQ是一个开源的消息队列中间件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;标准。它是一种可靠、可扩展、灵活和可插拔的解决方案&#xff0c;用于处理异步消息传递和事件驱动系统。…

HDFS的块汇报和块放置策略--从一次HDFS写文件故障开始(WIP)

文章目录 前言事故分析&#xff1a;代码解析BlockReport的调度和时机哪些Block会进行FBR或者IBRIBR所选定的BlockFBR所选定的Block 块放置策略详解之在上层寻找机器为文件添加块的基本流程块放置策略&#xff1a;选择机器为每个副本逐个寻找机器在指定范围内随机寻找简单看一下…

毕业论文word常见问题

0、前言&#xff1a; 这里的问题都是以office办公软件当中的word为例&#xff0c;和WPS没有关系。 1、页眉横线删不掉&#xff1a; 解决方案&#xff1a;进入页眉编辑状态&#xff0c;在开始选项栏中选择页眉字体样式&#xff0c;清除格式。 修改方式如下&#xff1a; 2、…

FL Studio21.8中文版深受欢迎的数字音频工作站(DAW)

在数字音乐制作领域&#xff0c;FL Studio21中文版作为一款深受欢迎的数字音频工作站&#xff08;DAW&#xff09;&#xff0c;因其强大的功能、用户友好的界面和对中文用户的优化支持而备受推崇。它广泛应用于音乐创作、编曲、录音、混音以及母带处理等领域&#xff0c;尤其适…