提示:这里是收集了和文件分享有关的文章
ArrayAdapter<String> adapter = new ArrayAdapter<String>(viewGroup.getContext(),
android.R.layout.simple_spinner_item, datas);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mSpinner.setAdapter(adapter);
mSpinner.setSelection(mPosition, true);
mSpinner.setOnItemSelectedListener(this);
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int position,
long id) {
。。。。。。
}
mSpinner.setOnItemSelectedListener(null);
mSpinner.setSelection(true);// 监听异步执行,延迟执行
mSpinner.setOnItemSelectedListener(this);
>>>>结果发现是先执行
监听置null | setOnItemSelectedListener(null) |
---|---|
设置值 | setSelection(true) |
监听置this | setOnItemSelectedListener(this) |
触发监听 | onItemSelected() |
监听白设置了
mSpinner.setSelection(true, false);
>>>>结果还是是执行监听onItemSelected()
mSpinner.setOnItemSelectedListener(null);
mSpinner.setSelection(true, false);// 监听同步执行,没延迟执行
mSpinner.setOnItemSelectedListener(this);
>>>>结果不执行监听onItemSelected(),满足要求
监听置null | setOnItemSelectedListener(null) |
---|---|
设置值 | setSelection(true, false) |
触发监听 | onItemSelected() |
监听置this | setOnItemSelectedListener(this) |
setSelection(int position) | Sets the currently selected item. | 设置当前选中的项目。 |
---|---|---|
setSelection(int position, boolean animate) | Jump directly to a specific item in the adapter data. | 直接跳转到适配器数据中的特定项目。 |
@Override
public void setSelection(int position) {// 3
setNextSelectedPositionInt(position);// android.widget.AdapterView
requestLayout();
invalidate();// 刷新
}
/**
* 保持 mNextSelectedPosition 和 mNextSelectedRowId 同步的实用程序
* @param position 下次我们去时 mSelectedPosition 的预期值
* 通过布局
*/
void setNextSelectedPositionInt(int position) {
mNextSelectedPosition = position;// 决定当前选中的是哪一个位置的值:3
mNextSelectedRowId = getItemIdAtPosition(position);
// 如果我们试图同步到选择,也更新它
if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) {// mNeedSync = false
。。。
}
}
/**
* 覆盖以防止向自己发送布局请求垃圾邮件
* 当我们放置视图时
* @see android.view.View#requestLayout()
*/
@Override
public void requestLayout() {
if (!mBlockLayoutRequests) {// mBlockLayoutRequests = false,因此执行
super.requestLayout();// 请求重新布局,此时会触发onLayout方法
}
}
requestLayout() | 要求parent view重新进行一次测量、布局、绘制这三个流程来更新自己位置。 | 重新布局自己在父布局中的位置 |
---|---|---|
invalidate() | view进行重新绘制 | 强制调用自己的onDraw()方法 |
会异步执行layout(int delta, boolean animate):
android.widget.Spinner
/**
* @see android.view.View#onLayout(boolean,int,int,int,int)
* Creates and positions all views
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mInLayout = true;
layout(0, false);
mInLayout = false;
}
/**
* 创建并定位此 Spinner 的所有视图。
* @param delta 更改所选位置。 +1 表示选择向右移动,
* 所以视图向左滚动。 -1 表示选择向左移动。
*/
@Override
void layout(int delta, boolean animate) {
。。。
if (mNextSelectedPosition >= 0) {// 要设置的位置
setSelectedPositionInt(mNextSelectedPosition);// mSelectedPosition = mNextSelectedPosition = 3
}
recycleAllViews();
removeAllViewsInLayout();
// Make selected view and position it
mFirstPosition = mSelectedPosition;
if (mAdapter != null) {
View sel = makeView(mSelectedPosition, true);// 生成AppCompatTextView{mText ="3"}
。。。。。。
}
// Flush any cached views that did not get reused above
mRecycler.clear();
invalidate();//刷新
checkSelectionChanged();// android.widget.AdapterView
mDataChanged = false;
mNeedSync = false;
setNextSelectedPositionInt(mSelectedPosition);
}
android.widget.AdapterView
/**
* 布局后调用判断选择位置是否需要被更新。 也用于触发任何未决的选择事件。
*/
void checkSelectionChanged() {
// 3 != -1,执行selectionChanged();
if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
selectionChanged();
mOldSelectedPosition = mSelectedPosition;
mOldSelectedRowId = mSelectedRowId;
}
// If we have a pending selection notification -- and we won't if we
// just fired one in selectionChanged() -- run it now.
if (mPendingSelectionNotifier != null) {// null
mPendingSelectionNotifier.run();
}
}
void selectionChanged() {
// 即将发布或运行选择通知程序,所以我们不需要一个挂起的通知器。
mPendingSelectionNotifier = null;
// 辅助功能服务AccessibilityService(无障碍服务)
// 如果spinner的监听为null则不触发,此时afm 不为null
// 如果spinner的监听不为null则触发,此时afm 不为null
if (mOnItemSelectedListener != null
|| AccessibilityManager.getInstance(mContext).isEnabled()) {
if (mInLayout || mBlockLayoutRequests) {
。。。。。。
if (mSelectionNotifier == null) {
mSelectionNotifier = new SelectionNotifier();
} else {
removeCallbacks(mSelectionNotifier);
}
post(mSelectionNotifier);// 有监听,执行这句
} else {
dispatchOnItemSelected();
}
}
。。。。。。
}
private class SelectionNotifier implements Runnable {
public void run() {
。。。。。。
if (mDataChanged && getViewRootImpl() != null
&& getViewRootImpl().isLayoutRequested()) {
。。。。。。
} else {
dispatchOnItemSelected();// 执行这句
}
}
}
private void dispatchOnItemSelected() {
fireOnSelected();// 执行这句
performAccessibilityActionsOnSelected();
}
private void fireOnSelected() {
if (mOnItemSelectedListener == null) {// 对接外部的Spinner监听
return;
}
final int selection = getSelectedItemPosition();
if (selection >= 0) {
View v = getSelectedView();
mOnItemSelectedListener.onItemSelected(this, v, selection,
getAdapter().getItemId(selection));// 执行这句
} else {
mOnItemSelectedListener.onNothingSelected(this);
}
}
监听置null | setOnItemSelectedListener(null) |
---|---|
设置值 | setSelection(true) |
请求重新布局 重新测量布局绘制 会触发onLayout方法 |
requestLayout() ->View的测量 performMeasure() ->View的布局 performLayout() ->View的绘制 performDraw() |
刷新onDraw | invalidate() |
监听置this | setOnItemSelectedListener(this) |
延迟 | 延迟 |
设置自身和子布局的位置 调用子元素的layout方法 完成View树的layout过程 |
onLayout(boolean changed, int l, int t, int r, int b) |
确定View本身的位置 即设置View本身的四个顶点位置 |
layout(0, false) |
选项更新 | checkSelectionChanged() ->selectionChanged() ->有监听事件则post(mSelectionNotifier ->dispatchOnItemSelected() ->fireOnSelected() ->mOnItemSelectedListener.onItemSelected() |
触发外部监听 | onItemSelected() |
android.widget.AbsSpinner
/**
* 直接跳转到适配器数据中的特定项目
*/
public void setSelection(int position, boolean animate) {
// 仅当请求的位置已经在屏幕上某处时才进行动画处理
boolean shouldAnimate = animate && mFirstPosition <= position &&
position <= mFirstPosition + getChildCount() - 1;
setSelectionInt(position, shouldAnimate);
}
/**
* 选中提供位置的项目
* @param position 要选择的位置
* @param animate 过渡是否动画
*/
void setSelectionInt(int position, boolean animate) {
if (position != mOldSelectedPosition) {// 3 != -1
mBlockLayoutRequests = true;
int delta = position - mSelectedPosition;// 要设置的位置-上次选中的位置=3-0=3
setNextSelectedPositionInt(position);// android.widget.AdapterView
layout(delta, animate);// 执行这句 android.widget.Spinner layout(3, false)
mBlockLayoutRequests = false;
}
}
>>>>执行layout(delta, animate) 就和 之前的一样
监听置null | setOnItemSelectedListener(null) |
---|---|
设置值 | setSelection(true, false) ->setSelectionInt() |
确定View本身的位置 即设置View本身的四个顶点位置 |
layout(3, false) |
选项更新 | checkSelectionChanged() ->selectionChanged() ->无监听事跳过post(mSelectionNotifier) |
监听置this | setOnItemSelectedListener(this) |
@Override
public void setAdapter(SpinnerAdapter adapter) {
。。。。。。
super.setAdapter(adapter);
mRecycler.clear();
。。。。。。
}
android.widget.AbsSpinner
@Override
public void setAdapter(SpinnerAdapter adapter) {
。。。。。。
requestLayout();
}
mCheckBox.setOnCheckedChangeListener(this);
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
。。。。。。
}
mCheckBox.setOnCheckedChangeListener(null);
mCheckBox.setChecked(true);// 不会触发监听
mCheckBox.setOnCheckedChangeListener(this);
>>>>结果OK
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.isPressed()) {
。。。。。。
}
}
mSeekBar.setOnSeekBarChangeListener(this);
// 拖动条进度改变的时候调用(不触发监听,修改显示值)
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
。。。。。。
}
}
// 拖动条开始拖动的时候调用
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
。。。。。。
}
// 拖动条停止拖动的时候调用(触发监听,修改参数)
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
。。。。。。
}
mSeekBar.setProgress(progress);
>>>>结果OK
提示:这里是参考的相关文章
博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持! |
---|
转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/126637399