针对你这种状况,最简单的一种办法是,设置两个TextView的宽度为固定值,且相等。LinearLayout
是一种线性排列的布局,布局中的控件从左到右(或者是从上到下)依次排列。wrap_content
依据其内容分配宽度,“用户名”和“密码”因为内容长度不一样,致使对应的两个TextView不等宽,而其后紧跟EditText,这就致使了不对齐。
第2种方法,把LinearLayout中的组件宽度设置为0dp,而后设置其android:layout_weight
,好比TextView设置为0.2,EditText设置为0.8,这两个控件就会按比例分配整个LinearLayout的宽度。第二个LinearLayout也一样设置,就能够保证EditText对齐。
第3种方法,使用RelativeLayout
,经过android:layout_alignLeft="@id/anotherViewId"
设置该View的左边和指定View的左边对齐。html
经过代码动态添加的Fragment,须要在布局文件中为 Fragment 添加一个FrameLayout容器,以安排 Fragment 在 activity 视图中的位置。
在FrameLayout视图的子组件中,layout_weight
属性无效。须要经过 layout_gravity
属性值决定子组件在 FrameLayout 视图中的位置。
对于水平方向的 LinearLayout,查看 layou_width 和 layout_weight 以决定子组件的宽度。java
若是父视图是LinearLayout,那么就能够直接调用textView.setLayoutParams(params),而后在添加textView到LinearLayout。
若是父视图是RelativeLayout 或者 FrameLayout,上面的作法无效,解决的办法是新建一个LinearLayout,而后把textView添加给它,再把这个LinearLayout添加给父视图。linux
除了配置当前的Activity android:windowSoftInputMode="stateVisible|adjustResize"
外,还须要:listView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
android
在 mipmap-[density]
路径中放app icon图片,仍然在 drawable-[density]
中放其它图片。
所以,在Manifest中引用app icon时 android:icon="@mipmap/ic_launcher"
,在其它须要引用图片的地方仍然用 @drawable/img1
.git
必定是在调用相似以下API的地方,应该赋予的是资源ID,而你却直接给了一个整数,错的View.setText(21)
,对的View.setText(R.string.search);
github
实现方式应该是FrameLayout
, 包含一个占满所有layout的ImageView,一个底部的TextView,一个右上角的用于显示数字的某种view。sql
经过一个App: Development.apk 获取一个Android App APK的全部Activity类名。它是默认安装在Android模拟器里的app,目的是方便测试和debug,其中一个功能叫Package Browser
,能够看到App内的全部的activity.shell
只有当Activity向外声明了本身是能够处理某些 intent action 时,第三方 app 才能经过 intent 去启动它,不然将致使崩溃。经过配置文件中的intent过滤器来声明。
当知道了package name和class name,能够这样去启动第三方的activity:intent.setComponent(new ComponentName(pkg, cls))
数据库
这应该是不可能的,除非你有系统相机的源码,修改源码,而后在系统相机内直接启动你想启动的activity。但是为何想要这样直接传递到新的activity呢?这多么费力不讨好啊。
不管是经过显示的仍是隐式的intent,启动第三方的activity,应该总要返回到本身的activity,在onActivityResult()
中处理返回的数据和结果。
因此我猜,你想实现的那种“直接”的效果,应该是在onActivityResult
中拿到图片后,再次启动了另外一个新的activity。
我作了一个测试:在A中启动B;B返回后,在A的onActivityResult中启动C。视觉上,B直接跳到了C。json
在manifest中配置activity的属性 android:configChanges="keyboardHidden|orientation|screenSize"
后,就容许Activity本身处理屏幕方向的变化,避免了被系统销毁。也就是说,相应的生命周期方法不会被调到。
而后为某一个Activity添加MenuItem,在Item的点击事件中启动上面配置的activity;
同时要注意,须要调用searchView.setIconifiedByDefault(false)
,这样启动的这个可搜索的activity的searchView才是展开的。
根据API说明,你的问题的关键在于onQueryTextSubmit()
的返回值:只有返回false,才能使SearchView发起一个intent。若是返回true,就认为这个submit已经被listener本身处理掉了。修改返回值为fasle,解决问题。
Unfortunately, there is no easy way to change the SearchView icon to a custom drawable, since the theme attribute searchViewSearchIcon is not public. See this answer for details.
为action bar提供了自定义的布局,放弃使用android提供的Home键android.R.id.home
做为UpIndicator。而是在这个布局中添加一个ImageView,这样就能够自定义你须要的间距离。而后实现ImageView.OnClickListener
,点击时返回父activity。
我目前就测试到这两种状况会致使重叠:
可能1.经过代码或者布局文件,向同一个位置添加了2次Fragment;
设备旋转时保存Activity的交互状态: onSaveInstanceState()
;
设备旋转时保存Fragment的交互状态: setRetainInstance(true)
;
设备旋转时保存WebView的数据: android:configChanges="keyboardHidden|orientation|screenSize"
;
设备旋转时保存在自定义View中绘制的图形。
SimpleBackPage是enum类型,意图是经过数字获取对应的Fragment类:
SimpleBackPage page = SimpleBackPage.getPageValue(pageValue); // 若是pageValue=1,getCls返回的就是FeedBackFragment.class // 若是pageVaule=2,getCls返回的就是AboutFrament.class page.getCls(); public enum SimpleBackPage { FEEDBACK(1, R.string.setting_about, FeedBackFragment.class), ABOUT(2, R.string.setting_about, AboutFrament.class); private SimpleBackPage(int values, int title, Class<?> cls) { this.values = values; this.title = title; this.cls = cls; } public Class<?> getCls() { return cls; }
当拿到Fragment类后,Fragment.class.newInstance()
经过调用该类的无参数构造器,建立并返回该类的一个实例,等价于:new Fragment()
。
this.viewPager.setOnPageChangeListener(this);
追问:“首次进入界面时,显示第一个页面时相应的按钮颜色已经变成点击后的状态?”。
追答:首次进入界面时onPageSelected不会被调到。能够经过viewPager.setCurrentItem(0) 触发它。
Fragment
是attach在Activity
上的,crash的缘由显然是你在尝试调用notifyDataSetChanged
更新fragment时,该fragment的attached activity已经被销毁了:“IllegalStateException: Activity has been destroyed”。一个workaround是这样的:
// here you check the value of getActivity() and break up if needed if(getActivity() == null) { return; } // do your stuff to update fragment // ...
我按照你的流程写了一个demo,复现了你描述的bug现象。
当滑动ViewPager时,致使父fragment视图被销毁,即onDestroyView()
被调到,
再次滑动到该父fragment时,重建视图,即onCreateView()
被调到,ft.add()
被再次调到,再次添加2个子fragment,这就致使了你提到的问题,而并不是是ft.hide()
不起做用。
一个变通的方法能够解决这个问题,在commit以前先remove全部的子Fragment:
你的问题应该从生命周期和ViewPager的adapter来理解。
Fragment具备和Activity类似的生命周期,而且其生命周期方法由托管它的Activity调用。
当把一些Fragment放入ViewPager时,就须要adapter的支持,以管理这些Fragment。对于经常使用的两种adapter,FragmentStatePagerAdapter会销毁掉不须要的fragment,而FragmentPagerAdapter只是销毁了fragment的视图。
public class DatePickerDialog extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // 使用不带theme的构造器,得到的dialog边框距离屏幕仍有几毫米的缝隙。 // Dialog dialog = new Dialog(getActivity()); Dialog dialog = new Dialog(getActivity(), R.style.CustomDatePickerDialog); // must be called before set content dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(R.layout.dialog_datepicker); // 设置宽度为屏宽、靠近屏幕底部。 Window window = dialog.getWindow(); WindowManager.LayoutParams wlp = window.getAttributes(); wlp.gravity = Gravity.BOTTOM; wlp.width = WindowManager.LayoutParams.MATCH_PARENT; window.setAttributes(wlp); return dialog; }
PendingIntent.getActivity(...)
和 startActivity(intent)
两种方式启动的Activity都以一样的方法获取extra数据:PendingIntent.getActivity()
打包了一个Context.startActivity()
方法的调用,该方法告诉操做系统『我须要启动一个Activity』,随后调用PendingIntent.send()
方法时,操做系统会按照咱们的要求发送原来封装的intent。
可是使用PendingIntent须要特别注意:
获取的extra数据极可能是旧的:除非把第4个参数从0改为PendingIntent.FLAG_UPDATE_CURRENT
.
为了安全因素,最好只发送显示的intent.
PendingIntent.getActivity(...)
和 startActivityForResult(...)
两种方式(第2个参数都是requestCode)启动的Activity以一样的方法返回result:setResult(resultCode, intent)
。
而后在void onActivityResult(int requestCode, int resultCode, Intent data)
中根据resultCode
作相应的处理。
总结:仍是让PendingIntent
作它“字面上”该作的事情为好,好比经过AlarmManager定时作的任务,经过NotificationManager发送消息到通知栏,一种pending状态。让startActivity
启动应用内的Activity,启动其它应用:读取联系人、调用摄像头、发送社交圈,等等,须要马上响应的任务。
要正肯定义数据,以及初始化adapter的数据。这样定义数据是不可取的:
rivate String [] groupStr={"第一组","第二组","第三组"}; private String [] childStr={"first","second","third"}; private List<Map<String, String>> groupData = new ArrayList<Map<String, String>>(); private List<Map<String, String>> childData = new ArrayList<Map<String, String>>();
若是删除了child index=2元素,必然致使你的childData和groupData数量不对等,当adapter试图为group2调用getChildrenCount(int groupPosition)
时崩溃。
应该像这样定义child data: List<List<Map<String, ?>>>
.
缘由是你传入的context,也就是SumFileActivity
,并无实现你定义的IOnClickListener
。因此没法强制转型。既然你在Fragment中实现了接口,那咱们能够这样作,注册一个接口,替代传入context的办法,而后还须要作的事件就是,在建立MyDialog的Fragment里面调用setOnClickListener
.
虽然设置了setOnChildClickListener()
,但点击child list view item无反应,就我刚才测试来看,有两种状况:
第1种状况,isChildSelectable()
返回false
,已经被你排除了。
第2种状况,item的布局文件中,有控件劫持了点击事件(ListView
都存在这种状况)android:focusable="true"
。不配置TextView的这个属性(由于TextView默认是非聚焦的),或者设置为false,就能让item能响应点击事件。
而像CheckBox, Button, EditText等默认是可聚焦的,若是包含在list item layout内,并且还须要响应item的点击事件的话,那么必须设置为非聚焦。
关于getChildrenCount:
点击展开GroupItem时,getChildrenCount()
被调到,以返回这个Group的child数量(为避免出现数组越界的错误);而后adapter才会去调用getChildView()
。
关于getChildView()、getChild()、getGroup():
咱们须要覆写getChildView()
,以填充视图,那么首先要拿到数据,而getChild()
的目的就是拿到存储在adapter中对应位置的数据。固然,若是你在adapter以外维护了一个child data list,也能够直接从这个list中取数据。可是getChild()
看起来不是更清楚明了吗?getGroup()
也是一样的道理,在执行getGroupView()
填充group视图时,让你能够轻松地获取对应的数据。
本质上,ExpandableListAdapter 的getChild(), getGroup()
和 android.widget.Adapter 的 Object getItem(int position)
是一回事儿:『Get the data item associated with the specified position in the data set.』
简单来讲,是为了复用,避免每次从layout资源文件生成新的视图(或者是经过代码生成新的视图)。好比像ListView
或者GridView
,屏幕上若能显N个条目,那么getView
就被调用N次,以提供对应位置的视图。而复用以前已经生成的视图,能够提升效率。
你的代码已经成功地添加了context menu, 之因此长按无反应,缘由极可能是list item有组件截获了list的点击事件。检查list item的布局文件,应该能够看到android:focusable="true"
。把它设置为false.
错误提示信息告诉你问题出在这:『at android.widget.ArrayAdapter.getView(ArrayAdapter.java:369』
你须要了解默认的getView方法的实现:
在adapter的构造方法中指定的布局(android.R.layout.simple_list_item_1)是Android SDK 提供的预约义布局资源。该布局拥有一个TextView根元素。而默认的ArrayAdapter<T>.getView(...)实现方法依赖于toString()方法。它首先生成布局视图,而后找到指定位置的对象并对其调用toString()方法,最后获得字符串信息并传递给TextView。
因此,我猜问题应该是你传给Adapter的dataList包含null对象。你应该着重检查更改adapter数据的代码。
经过bound service实现后台下载,这样,显示下载状态的UI组件被销毁再重建时,经过绑定service就能够正确显示下载状态。固然下载任务必须交给工做线程(好比AsyncTask),由bound service启动AsyncTask,经过广播或者接口的方式,应用组件就能够获取下载状态。
针对Android,若是App不在前台的话,能够经过service完成:
使用IntentService在后台抓取服务器的最新数据;
使用AlarmManager和PendingIntent安排服务的运行(设置service查询的间隔时间);
使用Notification从后台通知用户(用户下拉通知栏后能够看到详细信息,点击后进入App)。
从官方文档看,应该是为了得到其余APP的通知内容从而在本身的锁屏界面上显示。you can designate whether a notification from your app is visible on the lock screen.
在4.2的机器上测试,没法作到。
须要在子线程执行完成的地方,经过主线程的Handler发送一条消息;主线程收到消息后执行。
主线程是UI线程,不要试图让UI线程等待某个结果,以后再往下执行,这会致使UI卡顿。UI线程是一直循环的,咱们须要经过消息机制通知UI线程去作一些事情。
你既然想在主线程以外执行recorder.start()
,因此关键在于你代码中的mhandler是谁建立的? 若是是在UI线程中建立的,那么你经过mhandler.sendMessage
或者post(Runnable)
这些方式,相应的代码仍将在主线程中执行。
方法1:ScrollView內的子View消耗了它的点击事件,因此一个解决办法是,为它的子View设置setOnClickListener
. (这种办法,我测试了可行)
方法2:设置全部子View的xml属性android:clickable="false"
, 而后实现ScrollView的setOnClickListener
方法。(这种方法来自OnClickListener on scrollView,我测试了不行,但解决了别人的问题)
为数组里的每个图片设置一个tag:ImageView.setTag(Objcet tag)
,
在onClick中经过tag识别图片:((ImageView)v).getTag()
R.layout.menu_frame
包含一个FrameLayout
,这只是一个空的布局,你能够把它当作一个Fragment的容器。SlidingMenu提早注册了一个空的布局,须要你用本身的menu去替换它:.replace(R.id.menu_frame, new SampleListFragment())
你并无替换,因此看到的是空的。这种作法的本质是把一个包含menu的Fragment视图添加给Activity。
AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setSingleChoiceItems(R.array.test, 0, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ListView lw = ((AlertDialog) dialog).getListView(); // which表示点击的条目 Object checkedItem = lw.getAdapter().getItem(which); // 既然你没有cancel或者ok按钮,因此须要在点击item后使dialog消失 dialog.dismiss(); // 更新你的view mButton.setText((String)checkedItem); } }); AlertDialog dialog = builder.create(); dialog.show();
android:alpha="0.5"
alpha property of the view, as a value between 0 (completely transparent) and 1 (completely opaque). Related Methods:
setAlpha(float)
若是你想获得已显示的字符个数,或者未显示的字符个数,那么其中的关键是如何计算每个字符的宽度。而后遍历这个字符串,当前n个字符宽度总和,超过TextView宽度时,就获得了已显示的字符个数。
若是须要存储用户配置,好比某些选项是容许仍是禁止,或者是搜索框的历史记录,可使用 shared preferences,它是一种存储key-value的xml文件,能够实现轻量级数据的永久存储,使用SharedPreferences类读写。
若是须要存储少许的、简单的数据,可使用Json文件。
若是须要存储大量的、复杂的数据,好比一个跑步运动App,持续追踪用户的跑步路线,那就须要存储大量的地理位置数据。而SQLite是一个轻量级的开源跨平台库,并具备一套强大的关系型数据库API可供使用,数据在磁盘上单个文件的形式存在。Android为SQLite提供了不少类,能够很方便的完成对数据库的读写操做。
对API存疑的时候,最快的方式是查看API文档:Passing null will return all columns / all rows for the given URI.
咱们把json文件从新排列,目的是为了呈现其清晰的嵌套结构。所以,能够注意到,json包含这些元素:
由[]
括起来的称之为数组JSONArray
;
由{}
括起来的称之为JSONObject
;
字符串String
;boolean, double, int, long
基本数据类型;
经过JSON Object的方法获取这些数据,好比string:JSONObject.getString(String name)
而后根据JSON文件的结构,一层一层地解析。
发现你最近也有提Android相关的问题,那我就经过Android ListView item的点击事件,一种使用频率很高的view,经过它认识“回调”,可能有助于理解。
好比ListView包含几个概略信息条目,你想点击某个条目跳到详情界面。
mListView.setOnItemClickListener(new OnItemClickListener() { ... });
就已经实现了一个回调(implements a callback interface)。
接下来发生的事情咱们就知道了,点某个条目就跳到其详情界面。
问题是,谁去调(call)它呢?咱们在实现(implements)这个回调时,为何必需要override其中的方法呢?
// 当view被点到时,performItemClick就被调到,处理点击带给view的变化,除此以外,
// AdapterView还想到了,“若是其它类想在点击发生时作点儿事情,该怎么办呢?”
// 经过接口。
// (1)我来定义接口,把知道的信息(被点到的view、position、id)告诉你;
// (2)你来实现接口,而后把实现的接口告诉我。
OnItemClickListener是接口,不是内部类。接口须要你去implement。
通常的作法是:listview.setOnItemClickListener(mListener)
,而后定义这个listener,并实现其接口规定的方法。
不理解你如此定义 new ListView. OnItemClickListener()
的意图,但之因此出错,也许你是没有导入 import android.widget.AdapterView.OnItemClickListener
。
能够继承 Application
类以保存全局的“application state”。由于这些变量是全局的,因此应用的全部组件均可以获取/更改这些变量。多数状况下,静态单例模式能够提供相同的功能。
shell:/ $ pm list packages shell:/ $ pm list packages -f shell:/ $ dumpsys package com.tencent.mm | grep versionName
这样的 app 要放在 Android bsp 相应的目录中,经过 Android.mk 文件编译,这才能获取某些特殊权限,这些权限是经过集成编译器没法获取的。
须要在Storyboard中把UIView的类名修改成你自定义的类名:点击位于Storyboard的CustomView,在右侧的选项卡中,点击Identity Inspector选项卡,而后修改Custom Class;
而后把这个CustomView从Storyboard中拖到ViewController中,创建IBOutlet;
这样你就拥有了这个CustomView的实例了,而后就能够修改它的属性,调用它的方法。
能够参考这个demo工程。若是你是想经过Storyboard来完成这件事情,就用不着initWithframe,这个方法的目的是用代码生成一个指定frame的view。
@interface MainViewController () <FristSectionCollectionViewCellDelegate> self.fristSectionCollectionViewCell.delegate = self;
虽然你实现了delegate相应的方法,但若是不给delegate赋值,那么以下的判断将为false:if ([_delegate respondsToSelector:@selector(choseTerm:)])
。一个demo。
严格讲,上述提示并非出错的约束,而是多余的约束,好比设置了上、下边距,同时又pin了高度,就会致使出现这样的问题。感受你的问题应该是设置了UIView:0x166ea400高度为37,而后又设置它等于另外一个UIView:0x16526700宽度的0.0894。这样就冗余了。
而排查的方法是,在storyboard中挨个找UIView,37是个很好的切入点,我是这样作的,很笨。
若是你想实现“不须要拖动就能够显示UICollectionView的所有内容”,前提是你为UICollectionView分配的layout必需要容得下全部的UICollectionViewCell.
若是知足这个前提,好比你想显示的UICollectionView包含9个cell,每一个cell大小相同,就像一个九宫格。
你必须设置每一个cell的frame size:
// 设置指定位置cell的frame size - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView == self.myCollectionView) { CGRect collectionViewFrame = self.myCollectionView.frame; CGFloat cellWidth = collectionViewFrame.size.width/kCollectionViewCols; CGFloat cellHeight = collectionViewFrame.size.height/kCollectionViewRows; return CGSizeMake(cellWidth, cellHeight); } }
根据父view的frame.origin.x
和frame.size.width
,以及子view的宽度,计算子view的横坐标x,应该是父x + 父w/2 - 子w/2
,而后CGRectMake
。
严格讲,你这句话『sizeof(arr) =10; 这里只是把地址传给sizeof啊』是错误的,你传的是数组名,数组名不等价于地址。
编译器用数组名标记数组的属性,好比具备肯定数量的元素。而你说的地址,也就是指针,只是一个标量值。
只有当数组名在表达式中使用时,编译器才会为它产生一个指针常量。而只有如下两种状况,才不被当作指针常量:
sizeof(数组名):返回数组长度(所占的字节数,不是数组元素个数),而不是指向数组的指针的长度。
&数组名:产生一个指向数组的指针,而不是一个指向某个指针常量的指针。
版权声明:《分类整理我在 SegmentFault 上针对某些问题做的回答》由 WeiYi.Li 在 2015年11月29日写做。著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
文章连接:http://li2.me/2015/11/my-sf-a...