JAVA之XML学习总结11月09日[原贴]

本文介绍XML的基础知识,包括其用途、文档结构、元素定义及如何通过DTD和Schema进行文档约束。此外,还介绍了XML的两种主要解析方式:DOM和SAX。

 

XML<<可扩展的标记语言>>

(本人是新手)本原创贴为每天通过笔记整理的一些内容,只为了解自己的学习进度,不足之处请见谅

 

小知识点: Java虚拟机默认64MB 通过-Xmx可以增加内存。例:java-Xmx1000m 增加1G

 

XML主要目的:软件的配置文件,描述有关系的数据 , lXML现在已经是软件开发中一种通用的数据描述语言.

 

1)      声明:加上声明是一个格式良好的文件,<? Version”1.0” ?> 通常是ISO8859编码,所以必须声明encoding修改 例encoding”GB2312” standalone=”yes” 是不依赖其它文档

 

2)      元素定义:可以不含标签体<br/> 合理嵌套,不能交叉,只能有一个根标签,空格和换行被当做内容处理,在JAVA中也被识别成对象。

 

3)      其它:一个标签可以有多个属性,每个属性都有它自己的名称和取值,可以把不被解析的代码放在CDATA里面,

 

XML约束文档:主要是约束一个XML的文档的书写规范。

两种约束方式:XML-DTDXML-Schema  相对DTD容易理解好学,SchemaDTD复杂的相当的多。DTD只能用UTF-8uncode

xml中声明引入DTD约束文件名的两种方式

IE5以上内置一个XML解析工具:Micrsoft.XMLDOM; 通过JavaScript检查约束文件

:   xmldoc.validateOnParse = “true”; //打开解析检查;

        xmldoc.async = “false” //边装载边解析改成装载完再解析

        Var xmldoc = new AtiveXObject(“Microsoft.XMLDOM”)//拿到对象

        xmldoc.load(“xxx.xml”); //装入对象

        var reason = xmldoc.parseError.reason; //错误原因

       var line = xmldoc.parseError.line;  //错误行号

XML解析方式分为两种:DOMSAX;

 

DOM把所有xml装入内存形成一个树的形式(装入的是一个个标签(节点对象));

 

SAX是边装载边处理 主要是解析器和事件处理器,解析器读XML文档,向事件处理器发送事件,事件处理器对XML数据进行处理。startElement,endElement,characters比较常用。

 

XML解析器一般分为 crimson(sun公司)   xerces(IBM)  aelfred2(自由组织);

XML解析技术 就是说包装了解析器,API便于操作

Jaxp(sun公司推荐) jdom(没人用了) dom4j(性能完全优于JaxpJdom推荐使用)

newInstance    4种方法查找本地解析器;

Node对象 通过节点就可以操作整个文档 空白的地方和内容都被解析成对象#text

 

得到解析器对象的几个步骤1、得到创建解析器对象的工厂,2、创建一个解析器对象

3、关联解析的XML文件。

 l   javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式再输出 .最后对节点进行一些查找,删除,更新,增加。

 

 

  1<!DOCTYPE 文档根结点 SYSTEM "DTD文件的URL">
 2<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">
<think>我们正在实现一个自定义样式的时间期选择器,要求包括年、月、、时、分的选择。我们可以采用以下方案: 1. 使用第三方库(如WheelPicker)快速实现,并自定义样式 2. 完全自定义View,实现滑动选择器 考虑到开发效率和自定义样式的灵活性,这里推荐使用第三方库`com.contrarywind:Android-PickerView`(也称为WheelPicker)来实现,因为它支持多种选择器样式,并且可以自定义样式。 步骤: 1. 添加依赖 2. 创建选择器并设置类型为年、月、、时、分 3. 自定义样式(如文字大小、颜色、背景等) 但是,用户要求的是自定义样式的时间期选择器,所以我们重点放在如何自定义这个第三方库的样式上。 另外,我们也可以考虑使用Google Material Design中的`MaterialDatePicker`和`MaterialTimePicker`,但用户要求的是自定义样式,并且要在一个选择器中同时选择期和时间,所以可能还是需要自定义。 这里我们使用`Android-PickerView`来实现一个自定义的期时间选择器。 具体实现: 1. 在build.gradle中添加依赖: implementation 'com.contrarywind:Android-PickerView:4.1.9' 2. 创建布局文件,放置一个按钮用于触发选择器,以及一个TextView用于显示结果。 3. 编写代码,配置期时间选择器。 注意:`Android-PickerView`支持同时显示多个滚轮(年、月、、时、分),我们可以通过设置类型来实现。 示例代码: ```java public class MainActivity extends AppCompatActivity { private TextView tvTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvTime = findViewById(R.id.tv_time); findViewById(R.id.btn_show_picker).setOnClickListener(v -> showPicker()); } private void showPicker() { // 注意:这里我们使用自定义的OptionsPickerView,但是需要配置多个滚轮 // 由于库本身没有提供期时间一体的选择器,我们可以通过组合多个滚轮来实现 // 获取当前期和时间 Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); // 注意:月份从0开始 int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); // 创建选项列表 // 年(从当前年份前后扩展50年) final List<Integer> yearList = new ArrayList<>(); for (int i = year - 50; i <= year + 50; i++) { yearList.add(i); } // 月(1-12) final List<Integer> monthList = new ArrayList<>(); for (int i = 1; i <= 12; i++) { monthList.add(i); } // (根据年月动态变化,这里先初始化1-31) final List<Integer> dayList = new ArrayList<>(); for (int i = 1; i <= 31; i++) { dayList.add(i); } // 时(0-23) final List<Integer> hourList = new ArrayList<>(); for (int i = 0; i < 24; i++) { hourList.add(i); } // 分(0-59) final List<Integer> minuteList = new ArrayList<>(); for (int i = 0; i < 60; i++) { minuteList.add(i); } // 初始化选择器 OptionsPickerView pvCustomOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() { @Override public void onOptionsSelect(int options1, int options2, int options3, int options4, int options5) { // 返回的分别是五个滚轮的位置索引 int selectedYear = yearList.get(options1); int selectedMonth = monthList.get(options2); int selectedDay = dayList.get(options3); int selectedHour = hourList.get(options4); int selectedMinute = minuteList.get(options5); String time = String.format(Locale.getDefault(), "%d-%02d-%02d %02d:%02d", selectedYear, selectedMonth, selectedDay, selectedHour, selectedMinute); tvTime.setText(time); } }) .setLayoutRes(R.layout.picker_custom_layout, v -> { // 自定义布局中的控件 final TextView tvSubmit = v.findViewById(R.id.tv_finish); final TextView tvCancel = v.findViewById(R.id.tv_cancel); tvSubmit.setOnClickListener(v1 -> { pvCustomOptions.returnData(); pvCustomOptions.dismiss(); }); tvCancel.setOnClickListener(v1 -> pvCustomOptions.dismiss()); }) .isDialog(true) // 对话框样式 .build(); // 设置数据 pvCustomOptions.setPicker(yearList, monthList, dayList, hourList, minuteList); // 设置默认选中项 pvCustomOptions.setSelectOptions( yearList.indexOf(year), monthList.indexOf(month + 1), // 因为monthList是1-12,而Calendar的month是0-11 dayList.indexOf(day), hourList.indexOf(hour), minuteList.indexOf(minute) ); pvCustomOptions.setTitleText("选择期时间"); pvCustomOptions.show(); } } ``` 4. 自定义布局:在res/layout/picker_custom_layout.xml中定义选择器的头部和底部(例如标题、确定和取消按钮)。滚轮部分由库自动生成。 5. 自定义滚轮样式:可以通过PickerView的Builder设置样式,例如: ```java .setTextColorCenter(Color.BLACK) // 设置选中项文字颜色 .setTextColorOut(Color.LTGRAY) // 设置未选中项文字颜色 .setDividerColor(Color.GRAY) // 设置分割线颜色 .setTextSize(20) // 设置文字大小 .setContentTextSize(18) // 设置滚轮文字大小 ``` 但是,由于我们同时有五个滚轮,并且可能需要不同的标签(如年、月、、时、分),我们可以在自定义布局中为每个滚轮添加标签,或者使用库的setLabels方法: ```java pvCustomOptions.setLabels("年", "月", "", "时", "分"); ``` 6. 动态更新天数:由于每个月的天数不同,我们需要根据选择的年月来更新天数。可以在选择年或月后,重新计算天数并更新第三个滚轮的数据。但是,这个库目前不支持动态更新单个滚轮。因此,我们需要在年或月改变时,重新设置整个选择器的数据(包括年、月、、时、分),并重新设置选中位置。 这可能会有些复杂,我们可以通过重写OnOptionsSelectListener并在年或月改变时更新滚轮的数据。但是,由于库的限制,我们可能需要重新构建选择器。另一种方法是使用库的`setPicker`方法重新设置数据,并更新滚轮的数据。 我们可以在选择器的监听中,当用户改变年或月时,重新计算该年月的天数,然后更新滚轮数据。但是,注意:这个监听是在用户点击确定时才触发的。因此,我们需要在用户滑动年或月滚轮时动态更新滚轮,这需要设置滚轮的监听。我们可以通过设置滚轮的`OnItemSelectedListener`来实现。 但是,`Android-PickerView`的OptionsPickerView并没有提供每个滚轮的滚动监听。因此,我们可以使用`WheelView`的`setOnItemSelectedListener`,但是我们需要在自定义布局中找到这些滚轮。我们可以通过自定义布局,然后获取每个滚轮,并设置监听。 由于这个实现较为复杂,这里不展开。如果不需要实时更新天数,可以在用户选择确定后,检查期是否有效(如2月30),并提示用户重新选择。 7. 对于期时间选择,我们也可以分开选择:先选择期,再选择时间。这样可以使用库自带的期选择器和时间选择器,避免动态更新天数的问题。 总结:使用`Android-PickerView`可以快速实现自定义样式的时间期选择器,但对于动态更新天数需要额外处理。如果要求动态更新,可以考虑分开选择期和时间,或者使用其他支持动态更新的库。 另外,也可以考虑使用Google的Material Design组件中的`MaterialDatePicker`(用于期选择)和`MaterialTimePicker`(用于时间选择),然后组合它们。但是这样需要两个步骤。 根据需求选择方案。 下面给出一个使用Material Design组件的例子(需要添加依赖`com.google.android.material:material`): 期选择器: ```java MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker() .setTitleText("选择期") .setSelection(MaterialDatePicker.todayInUtcMilliseconds()) .build(); datePicker.addOnPositiveButtonClickListener(selection -> { // 选择期后,弹出时间选择器 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH); int day = calendar.get(Calendar.DAY_OF_MONTH); // 时间选择器 MaterialTimePicker timePicker = new MaterialTimePicker.Builder() .setTimeFormat(TimeFormat.CLOCK_24H) .setHour(12) .setMinute(0) .build(); timePicker.addOnPositiveButtonClickListener(v -> { int hour = timePicker.getHour(); int minute = timePicker.getMinute(); String time = String.format(Locale.getDefault(), "%d-%02d-%02d %02d:%02d", year, month+1, day, hour, minute); tvTime.setText(time); }); timePicker.show(getSupportFragmentManager(), "time_picker"); }); datePicker.show(getSupportFragmentManager(), "date_picker"); ``` 以上两种方案供选择。 由于用户要求在一个选择器中同时选择期和时间,我们重点在第一种方案(使用Android-PickerView)上进行了说明。 自定义样式:通过修改布局文件`picker_custom_layout.xml`和通过Builder设置滚轮样式,可以实现高度自定义。 相关问题: 1. 如何实现期时间选择器的循环滚动? 2. 如何动态更新期选择器中的天数? 3. 如何自定义时间选择器的分割线、文字颜色等样式? 4. 如何在时间选择器中添加AM/PM选项? 5. 如何限制时间选择器的可选范围(如只能选择未来时间)?</think>### Android Java 自定义样式期时间选择器实现指南 在 Android 中实现自定义样式的期时间选择器(包含年、月、、时、分),主要有三种实现方式,下面提供详细实现方案: #### 一、使用 Material Design 组件(推荐方案) Google 的 Material Design 库提供了高度可定制的期时间选择器: ```gradle // build.gradle implementation 'com.google.android.material:material:1.9.0' ``` ```java // 显示期选择器 private void showDatePicker() { MaterialDatePicker<Long> datePicker = MaterialDatePicker.Builder.datePicker() .setTitleText("选择期") .setSelection(MaterialDatePicker.todayInUtcMilliseconds()) .setTheme(R.style.CustomDatePicker) // 自定义主题 .build(); datePicker.addOnPositiveButtonClickListener(selection -> { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.setTimeInMillis(selection); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); // 保存选择的期 }); datePicker.show(getSupportFragmentManager(), "DATE_PICKER"); } // 显示时间选择器 private void showTimePicker() { MaterialTimePicker timePicker = new MaterialTimePicker.Builder() .setTimeFormat(TimeFormat.CLOCK_24H) .setHour(12) .setMinute(0) .setTheme(R.style.CustomTimePicker) // 自定义主题 .build(); timePicker.addOnPositiveButtonClickListener(dialog -> { int hour = timePicker.getHour(); int minute = timePicker.getMinute(); // 保存选择的时间 }); timePicker.show(getSupportFragmentManager(), "TIME_PICKER"); } ``` **自定义样式** (`res/values/styles.xml`): ```xml <style name="CustomDatePicker" parent="ThemeOverlay.MaterialComponents.MaterialCalendar"> <item name="materialCalendarStyle">@style/CustomCalendarStyle</item> <item name="colorOnSurface">@color/primary_text</item> </style> <style name="CustomCalendarStyle" parent="Widget.MaterialComponents.MaterialCalendar"> <item name="android:background">@drawable/bg_date_picker</item> <item name="daySelectedStyle">@style/CustomDaySelected</item> </style> <style name="CustomDaySelected" parent="Widget.MaterialCalendar.Day"> <item name="android:background">@drawable/bg_selected_day</item> </style> ``` #### 二、使用第三方库(如 WheelPicker) 实现更传统的滚轮式选择器: ```gradle implementation 'com.github.gzu-liyujiang.AndroidPicker:WheelPicker:4.1.11' ``` ```java private void showDateTimePicker() { DateTimePicker picker = new DateTimePicker(this); picker.setTopLineVisible(false); picker.setDividerType(WheelView.DividerType.FILL); picker.setDividerColor(ContextCompat.getColor(this, R.color.divider)); // 自定义文本样式 picker.setWheelItemTextSize(18); picker.setWheelItemTextColor( ContextCompat.getColor(this, R.color.text_normal), ContextCompat.getColor(this, R.color.text_selected) ); picker.setOnDateTimePickListener((year, month, day, hour, minute) -> { String datetime = String.format("%d-%02d-%02d %02d:%02d", year, month, day, hour, minute); // 处理选择的时间 }); picker.show(); } ``` #### 三、完全自定义视图(高级方案) 创建完全自定义的期时间选择器视图: ```java public class CustomDateTimePicker extends FrameLayout { private final WheelView yearWheel, monthWheel, dayWheel, hourWheel, minuteWheel; public CustomDateTimePicker(Context context) { super(context); LayoutInflater.from(context).inflate(R.layout.custom_datetime_picker, this); yearWheel = findViewById(R.id.year_wheel); monthWheel = findViewById(R.id.month_wheel); dayWheel = findViewById(R.id.day_wheel); hourWheel = findViewById(R.id.hour_wheel); minuteWheel = findViewById(R.id.minute_wheel); initWheels(); } private void initWheels() { // 初始化年份 (2020-2030) List<String> years = new ArrayList<>(); for (int i = 2020; i <= 2030; i++) { years.add(String.valueOf(i)); } yearWheel.setData(years); // 初始化月份 List<String> months = Arrays.asList("01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"); monthWheel.setData(months); // 初始化期 (1-31) List<String> days = new ArrayList<>(); for (int i = 1; i <= 31; i++) { days.add(String.format("%02d", i)); } dayWheel.setData(days); // 设置监听器更新天数 monthWheel.setOnWheelChangedListener((wheel, oldIndex, newIndex) -> updateDaysForMonth(monthWheel.getSelectedItemPosition() + 1) ); } private void updateDaysForMonth(int month) { int daysInMonth = getDaysInMonth(month); List<String> days = new ArrayList<>(); for (int i = 1; i <= daysInMonth; i++) { days.add(String.format("%02d", i)); } dayWheel.setData(days); } private int getDaysInMonth(int month) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MONTH, month - 1); return calendar.getActualMaximum(Calendar.DAY_OF_MONTH); } public String getSelectedDateTime() { return String.format("%s-%s-%s %s:%s", yearWheel.getSelectedItem(), monthWheel.getSelectedItem(), dayWheel.getSelectedItem(), hourWheel.getSelectedItem(), minuteWheel.getSelectedItem() ); } } ``` #### 四、自定义样式技巧 1. **圆角背景与阴影** (`res/drawable/bg_picker.xml`): ```xml <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="16dp"/> <solid android:color="@android:color/white"/> <stroke android:width="1dp" android:color="#E0E0E0"/> </shape> ``` 2. **深色模式适配**: ```xml <resources> <style name="CustomPickerTheme" parent="Theme.MaterialComponents.DayNight"> <item name="colorSurface">?attr/colorSurface</item> <item name="colorOnSurface">?attr/colorOnSurface</item> </style> </resources> ``` 3. **添加标签和单位**: ```java // 在自定义视图中添加标签 canvas.drawText("年", getWidth() * 0.1f, centerY - textOffset, mTextPaint); canvas.drawText("月", getWidth() * 0.3f, centerY - textOffset, mTextPaint); canvas.drawText("", getWidth() * 0.5f, centerY - textOffset, mTextPaint); canvas.drawText("时", getWidth() * 0.7f, centerY - textOffset, mTextPaint); canvas.drawText("分", getWidth() * 0.9f, centerY - textOffset, mTextPaint); ``` #### 五、性能优化建议 1. **视图复用**:使用 RecyclerView 实现滚轮选择器 2. **动态加载**:只初始化可见范围内的数据 3. **内存管理**:避免在滚动监听中执行重操作 4. **动画优化**:使用硬件加速的平移动画 > 完整实现参考:[Material DateTime Picker](https://github.com/wdullaer/MaterialDateTimePicker) [^1] > 或 [Android WheelPicker](https://github.com/gzu-liyujiang/AndroidPicker) [^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值