?持续更新,敬请关注......
?
原有的
android.support库已经废弃,建议使用androidx.preference,preference是一个非常简洁的设置页面,并且与系统界面拥有高契合度,让用户不会有太多的突兀感。
用官方的话来说就是
无需与设备存储空间交互,也不需要管理界面,便能构建交互式设置画面。此库自带 Material 主题,可在不同的设备和操作系统版本之间提供一致的用户体验。
以下将会通过简单的Demo实现Preference的样例
Demo演示图
build.gradle// Java language implementation implementation "androidx.preference:preference:1.2.0" // Kotlin implementation "androidx.preference:preference-ktx:1.2.0"
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingFragment())
.commit();
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/settings"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
public class SettingFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceClickListener {
private SharedPreferences sharedPreferences = null;
private Preference loginDjiAccount;
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
setPreferencesFromResource(R.xml.pref_setting, rootKey);
//用于取值的SharedPreferences
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
initView();
}
private void initView() {
loginDjiAccount = findPreference("login_dji_account");
if (loginDjiAccount != null) {
loginDjiAccount.setOnPreferenceClickListener(this);
}
}
@Override
public boolean onPreferenceClick(@NonNull Preference preference) {
switch (preference.getKey()) {
case "login_dji_account":
String rtmpUrlStr = sharedPreferences.getString("rtmp_url_pre", "");
if ("".equals(rtmpUrlStr)) {
Toast.makeText(getActivity(), "请在直播推流地址中随意填写值,再来点我...", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), "填写了:" + rtmpUrlStr, Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
return false;
}
}
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory app:title="DJI账户">
<Preference
app:key="login_dji_account"
app:summary="点击事件"
app:title="点我呀" />
<Preference
app:enabled="false"
app:key="logout_dji_account"
app:title="不可点击" />
</PreferenceCategory>
<PreferenceCategory
app:initialExpandedChildrenCount="0"
app:title="Dialog类型组件">
<EditTextPreference
app:enableCopying="true"
app:key="rtmp_url_pre"
app:summary="请设置"
app:title="直播推流地址"
app:useSimpleSummaryProvider="true" />
<ListPreference
app:enableCopying="true"
app:entries="@array/finishedAction"
app:entryValues="@array/finishedAction_values"
app:key="uav_finishedAction"
app:summary="返航"
app:title="任务结束动作"
app:useSimpleSummaryProvider="true" />
<MultiSelectListPreference
app:entries="@array/failSafe"
app:entryValues="@array/failSafe_values"
app:key="multi_select_list"
app:summary="悬停"
app:title="失控动作" />
</PreferenceCategory>
<PreferenceCategory app:title="其他的组件">
<Preference
app:summary="点击可以跳转到百度欸"
app:title="跳转Preference">
<intent
android:action="android.intent.action.VIEW"
android:data="http://www.baidu.com" />
</Preference>
<SwitchPreferenceCompat
app:key="uav_maxFlightRadiusEnabled"
app:selectable="true"
app:summary="设置无人机最大可飞行半径距离"
app:summaryOn="建议关闭此功能,否则将限制设备最大飞行距离"
app:title="限远开关" />
<EditTextPreference
app:dependency="uav_maxFlightRadiusEnabled"
app:key="uav_maxFlightRadius"
app:summary="2000"
app:title="限远(米)"
app:useSimpleSummaryProvider="true" />
<Preference
app:icon="@mipmap/ic_launcher"
app:key="icon"
app:summary="可以带Icon的Preference"
app:title="图标" />
<Preference
app:key="single_line_title"
app:singleLineTitle="true"
app:summary="但是下面的summary就不行了,它依然还是可以换行的,毕竟是注释信息嘛"
app:title="这个超级长,并且他不会换行,自带省略号的Preference" />
<DropDownPreference
app:entries="@array/finishedAction"
app:entryValues="@array/finishedAction_values"
app:key="dropdown"
app:title="点我!点我!点我!"
app:useSimpleSummaryProvider="true" />
<SeekBarPreference
app:defaultValue="20"
app:key="seekbar"
app:title="基本飞行速度(m/s)" />
</PreferenceCategory>
</PreferenceScreen>
以上为一个简单的Preference的使用
官方API androidx.preference
PreferenceCategory
用于对相似的Preference进行分组的容器。PreferenceCategory显示一个类别标题,将Preference进行分组归类。
PreferenceCategory示例 <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"> <PreferenceCategory app:icon="@mipmap/ic_launcher" app:initialExpandedChildrenCount="0" app:key="demo_key" app:summary="演示的作用" app:title="演示"> <EditTextPreference app:key="setting_name" app:title="设置用户名" /> <SwitchPreference app:defaultValue="false" app:key="setting_switch" app:title="Switch模式" /> <CheckBoxPreference app:summary="选择的内容" app:summaryOff="关闭summary" app:summaryOn="开启summary" app:title="选择项" /> </PreferenceCategory> </PreferenceScreen>
key 释义 app:icon设置图标 app:key设置key,类似于 android:idapp:summary子标题,类似于注释的作用 app:title标题 app:enabledtrue或false,设置是否可操作 app:initialExpandedChildrenCountvalue为int类型,类似于抽屉效果,int值为不隐藏的数量,与上图中显示 高级效果一致
Preference
类似于Button。可进行点击,具有大标题、小标题等。
Preference示例
<PreferenceCategory app:title="分组"> <Preference app:key="login_dji_account" app:summary="点击事件" app:title="点我呀" /> <Preference app:enabled="false" app:key="logout_dji_account" app:singleLineTitle="true" app:title="不可点击,虽然我超级长,但是我就不换行,打我呀" /> </PreferenceCategory>
key 释义 app:key设置key,类似于 android:idapp:summary子标题,类似于注释的作用 app:title标题 app:enabledtrue或false,设置是否可操作 app:icon设置图标 app:singleLineTitle设置为true时,超出屏幕部分自带省略号
Dialog类型组件
点击弹出Dialog组件。常见的有三种,输入框弹窗、单选弹窗、多选弹窗。
单选弹窗.png
多选弹窗.png
输入框弹窗.png <PreferenceCategory app:initialExpandedChildrenCount="0" app:title="Dialog类型组件"> <!--输入框--> <EditTextPreference app:enableCopying="true" app:key="rtmp_url_pre" app:summary="请设置" app:title="直播推流地址" app:useSimpleSummaryProvider="true" /> <!--单选--> <ListPreference app:enableCopying="true" app:entries="@array/finishedAction" app:entryValues="@array/finishedAction_values" app:key="uav_finishedAction" app:summary="返航" app:title="任务结束动作" app:useSimpleSummaryProvider="true" /> <!--多选--> <MultiSelectListPreference app:entries="@array/failSafe" app:entryValues="@array/failSafe_values" app:key="multi_select_list" app:summary="悬停" app:title="失控动作" /> </PreferenceCategory>
key 释义 app:enableCopying设置true时,用户可长按复制值 app:key设置key,类似于 android:idapp:summary子标题,类似于注释的作用 app:title标题 app:useSimpleSummaryProvider设置为true时,将会把选中或输入的值显示到summary中 app:entries该值是将array中的值作为显示值 app:entryValues当选中某项时,该值作为value进行存储
将该文件放入value文件夹
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="finishedAction"> <item>返航</item> <item>悬停</item> <item>最后一航点降落</item> <item>返回第一航点悬停</item> </string-array> <string-array name="finishedAction_values"> <item>GO_HOME</item> <item>NO_ACTION</item> <item>AUTO_LAND</item> <item>GO_FIRST_WAYPOINT</item> </string-array> <string-array name="failSafe"> <item>悬停</item> <item>降落</item> <item>返航</item> </string-array> <string-array name="failSafe_values"> <item>HOVER</item> <item>LANDING</item> <item>GO_HOME</item> </string-array> </resources>
可跳转的Preference
点击该组件,可跳转网页。
可跳转百度 <Preference app:summary="点击可以跳转到百度欸" app:title="跳转Preference"> <intent android:action="android.intent.action.VIEW" android:data="http://www.baidu.com" /> </Preference>
key 释义 app:summary子标题,类似于注释的作用 app:title标题 intent跳转组件 intent:data跳转地址
SwitchPreferenceCompat
该组件为开关组件,同时可通过该组件控制其他组件是否可操作。
控制开关.png <SwitchPreferenceCompat app:key="uav_maxFlightRadiusEnabled" app:summary="设置无人机最大可飞行半径距离" app:summaryOn="建议关闭此功能,否则将限制设备最大飞行距离" app:title="限远开关" /> <EditTextPreference app:dependency="uav_maxFlightRadiusEnabled" app:key="uav_maxFlightRadius" app:summary="2000" app:title="限远(米)" app:useSimpleSummaryProvider="true" />
key 释义 app:key设置key,类似于 android:idapp:summary子标题,类似于注释的作用,默认值 app:app:summaryOn打开时所显示的副标题 app:app:summaryOff关闭时所显示的副标题 app:title标题 app:dependency填写所属上级的id,可被填写ID的控件控制
DropDownPreference
该组件为下拉按钮弹窗,点击弹出的下拉弹窗将会在按钮旁显示.
点击前.png
点击后.png <DropDownPreference app:entries="@array/finishedAction" app:entryValues="@array/finishedAction_values" app:key="dropdown" app:title="点我!点我!点我!" app:useSimpleSummaryProvider="true" />
key 释义 app:key设置key,类似于 android:idapp:title标题 app:entries该值是将array中的值作为显示值 app:entryValues当选中某项时,该值作为value进行存储 app:useSimpleSummaryProvider副标题将会采用选中值
将该文件放入value文件夹
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="finishedAction"> <item>返航</item> <item>悬停</item> <item>最后一航点降落</item> <item>返回第一航点悬停</item> </string-array> <string-array name="finishedAction_values"> <item>GO_HOME</item> <item>NO_ACTION</item> <item>AUTO_LAND</item> <item>GO_FIRST_WAYPOINT</item> </string-array> <string-array name="failSafe"> <item>悬停</item> <item>降落</item> <item>返航</item> </string-array> <string-array name="failSafe_values"> <item>HOVER</item> <item>LANDING</item> <item>GO_HOME</item> </string-array> </resources>
SeekBarPreference
该组件为横向滑动条组件.
横向滑动条.png <SeekBarPreference app:defaultValue="20" app:key="seekbar" app:title="基本飞行速度(m/s)" />
key 释义 app:key设置key,类似于 android:idapp:title标题 app:defaultValue滑动条的默认值
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h