Android如何用DOM解析XML并实现表情弹出框?

来源:Nodejs社区作者:香港程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《Android如何用DOM解析XML并实现表情弹出框?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Android如何用DOM解析XML并实现表情弹出框?》有用,将其分享出去将是对创作者最好的鼓励。

在Android开发中,解析XML数据和实现表情弹出框是两类非常实用的功能,DOM解析适合处理结构明确的XML文件,表情弹出框则能提升聊天类应用的交互体验,下面分别讲解两种功能的实现方案。

Android如何用DOM解析XML并实现表情弹出框?

一、Android中使用DOM解析XML

DOM解析的核心是将整个XML文档加载到内存中,构建成节点树,之后通过遍历节点树获取需要的数据,适合XML文件较小、需要频繁操作节点的场景。

1. 准备XML测试文件

首先在项目的assets目录下创建emoji_config.xml文件,用于存储表情的基础配置信息,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<emoji_list>
    <emoji>
        <id>1</id>
        <name>微笑</name>
        <icon>emoji_smile</icon>
    </emoji>
    <emoji>
        <id>2</id>
        <name>大笑</name>
        <icon>emoji_laugh</icon>
    </emoji>
    <emoji>
        <id>3</id>
        <name>难过</name>
        <icon>emoji_sad</icon>
    </emoji>
</emoji_list>

2. DOM解析实现步骤

解析流程主要分为获取XML输入流、构建Document对象、遍历节点获取内容三个步骤,具体代码如下:

import android.content.Context;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

public class XmlParser {
    // 表情数据实体类
    public static class Emoji {
        public int id;
        public String name;
        public String icon;
    }

    // DOM解析XML方法
    public static List<Emoji> parseEmojiXml(Context context) {
        List<Emoji> emojiList = new ArrayList<>();
        try {
            // 1. 获取assets目录下的XML输入流
            InputStream is = context.getAssets().open("emoji_config.xml");
            // 2. 获取DocumentBuilderFactory实例
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 3. 获取DocumentBuilder实例
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 4. 解析输入流得到Document对象
            Document document = builder.parse(is);
            // 5. 获取根节点
            Element rootElement = document.getDocumentElement();
            // 6. 获取所有emoji节点
            NodeList emojiNodeList = rootElement.getElementsByTagName("emoji");
            // 7. 遍历emoji节点
            for (int i = 0; i < emojiNodeList.getLength(); i++) {
                Node emojiNode = emojiNodeList.item(i);
                if (emojiNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element emojiElement = (Element) emojiNode;
                    Emoji emoji = new Emoji();
                    // 获取id节点内容
                    NodeList idNodeList = emojiElement.getElementsByTagName("id");
                    if (idNodeList.getLength() > 0) {
                        emoji.id = Integer.parseInt(idNodeList.item(0).getTextContent());
                    }
                    // 获取name节点内容
                    NodeList nameNodeList = emojiElement.getElementsByTagName("name");
                    if (nameNodeList.getLength() > 0) {
                        emoji.name = nameNodeList.item(0).getTextContent();
                    }
                    // 获取icon节点内容
                    NodeList iconNodeList = emojiElement.getElementsByTagName("icon");
                    if (iconNodeList.getLength() > 0) {
                        emoji.icon = iconNodeList.item(0).getTextContent();
                    }
                    emojiList.add(emoji);
                }
            }
            // 关闭输入流
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return emojiList;
    }
}

3. 解析结果使用

在Activity中调用解析方法即可获取表情列表:

import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 解析XML获取表情列表
        List<XmlParser.Emoji> emojiList = XmlParser.parseEmojiXml(this);
        Toast.makeText(this, "解析到" + emojiList.size() + "个表情", Toast.LENGTH_SHORT).show();
    }
}

二、实现表情弹出框

表情弹出框通常使用PopupWindow实现,点击触发按钮时弹出,内部展示表情网格,点击表情后回调选择结果。

1. 弹出框布局文件

创建popup_emoji.xml作为弹出框的布局,内部使用GridView展示表情:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@android:color/white">

    <GridView
        android:id="@+id/gv_emoji"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:numColumns="4"
        android:verticalSpacing="10dp"
        android:horizontalSpacing="10dp"
        android:padding="10dp"
        android:gravity="center"/>
</LinearLayout>

2. 表情网格适配器

创建适配器绑定表情数据到GridView

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import java.util.List;

public class EmojiAdapter extends BaseAdapter {
    private Context context;
    private List<XmlParser.Emoji> emojiList;
    private LayoutInflater inflater;

    public EmojiAdapter(Context context, List<XmlParser.Emoji> emojiList) {
        this.context = context;
        this.emojiList = emojiList;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return emojiList.size();
    }

    @Override
    public Object getItem(int position) {
        return emojiList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item_emoji, parent, false);
            holder = new ViewHolder();
            holder.ivEmoji = convertView.findViewById(R.id.iv_emoji);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        // 这里假设表情图标放在res/drawable目录下,根据icon名称获取资源id
        XmlParser.Emoji emoji = emojiList.get(position);
        int resId = context.getResources().getIdentifier(emoji.icon, "drawable", context.getPackageName());
        holder.ivEmoji.setImageResource(resId);
        return convertView;
    }

    static class ViewHolder {
        ImageView ivEmoji;
    }
}

对应的单个表情布局item_emoji.xml内容:

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/iv_emoji"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:scaleType="centerInside"/>

3. PopupWindow实现逻辑

在Activity中初始化PopupWindow,绑定数据和点击事件:

import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.PopupWindow;
import androidx.appcompat.app.AppCompatActivity;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private PopupWindow emojiPopup;
    private Button btnShowEmoji;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnShowEmoji = findViewById(R.id.btn_show_emoji);
        // 点击按钮弹出表情框
        btnShowEmoji.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showEmojiPopup();
            }
        });
    }

    private void showEmojiPopup() {
        if (emojiPopup == null) {
            // 解析XML获取表情数据
            List<XmlParser.Emoji> emojiList = XmlParser.parseEmojiXml(this);
            // 加载弹出框布局
            View popupView = LayoutInflater.from(this).inflate(R.layout.popup_emoji, null);
            GridView gvEmoji = popupView.findViewById(R.id.gv_emoji);
            EmojiAdapter adapter = new EmojiAdapter(this, emojiList);
            gvEmoji.setAdapter(adapter);
            // 设置GridView点击事件
            gvEmoji.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    XmlParser.Emoji selectedEmoji = emojiList.get(position);
                    // 这里可以处理表情选择后的逻辑,比如插入输入框
                    btnShowEmoji.setText("选择了:" + selectedEmoji.name);
                    emojiPopup.dismiss();
                }
            });
            // 初始化PopupWindow
            emojiPopup = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
            // 设置背景,点击外部可关闭
            emojiPopup.setBackgroundDrawable(new ColorDrawable());
            // 设置动画
            emojiPopup.setAnimationStyle(android.R.style.Animation_InputMethod);
        }
        // 显示PopupWindow,在按钮下方弹出
        emojiPopup.showAsDropDown(btnShowEmoji, 0, 10);
    }
}

4. 主界面布局

主界面activity_main.xml只需要一个触发按钮:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center_horizontal">

    <Button
        android:id="@+id/btn_show_emoji"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="显示表情框"/>
</LinearLayout>

三、注意事项

  • DOM解析会将整个XML加载到内存,如果XML文件过大可能导致内存溢出,此时建议换用SAX或者Pull解析。
  • PopupWindow需要设置合理的宽高,同时记得设置背景,否则点击外部可能无法关闭弹出框。
  • 表情资源需要提前放到对应的目录下,确保资源名称匹配,避免获取资源id失败。

AndroidDOM解析XML表情弹出框PopupWindow修改时间:2026-06-06 14:30:57

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。