系统网站正在升级更新中中currop是什么意思

广播电视节目制作经营许可证:(沪)字第1248号
网络文化经营许可证:沪网文[6号
信息网络传播视听节目许可证:0910417
互联网ICP备案:沪ICP备号-3
沪ICP证:沪B2-
违法不良信息举报邮箱:
违法不良信息举报电话: 转 31594人阅读
1, Android Support V4, V7, V13是什么?
本质上就是三个java library。
2, 为什么要有support库?
如果在低版本Android平台上开发一个应用程序,而应用程序又想使用高版本才拥有的功能,就需要使用Support库。
3, 三个Support 库的区别和作用是什么?
Android Support v4 是最早(2011年4月份)实现的库。用在Android1.6 (API lever 4)或者更高版本之上。它包含了相对V4, V13大的多的功能。
例如:Fragment,NotificationCompat,LoadBroadcastManager,ViewPager,PageTabAtrip,Loader,FileProvider 等。
详细API 参考
Android Support v7: 这个包是为了考虑Android2.1(API level 7) 及以上版本而设计的,但是v7是要依赖v4这个包的,也就是如果要使用,两个包得同时 被引用。
v7支持了Action Bar。
Android Support v13:这个包的设计是为了android 3.2及更高版本的,一般我们都不常用,平板开发中能用到。
sdk\extras\android\support\samples\Support7Demos笔记
FloatingActionButton
代码分析:
关于log:需要使用Log输出一些信息。那么我们就需要使用到Log FrameWork。使用及注释如下
public void initializeLogging() {
LogWrapper logWrapper = new LogWrapper();
* Log的消息传递是依据一个链路依次传递的,Log传递到LogWrapper,LogWrapper传递到MessageOnlyLogFilter,MessageOnlyLogFilter传递到LogFragment
Log.setLogNode(logWrapper);
MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
logWrapper.setNext(msgFilter);
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
Log.i(TAG, "Ready");
涉及到的主要的类:
package com.mon.
* Helper class for a list (or tree) of LoggerNodes.
* &p&When this is set as the head of the list,
* an instance of it can function as a drop-in replacement for {@link android.util.Log}.
* Most of the methods in this class server only to map a method call in Log to its equivalent
* in LogNode.&/p&
public class Log {
public static final int NONE = -1;
public static final int VERBOSE = android.util.Log.VERBOSE;
public static final int DEBUG = android.util.Log.DEBUG;
public static final int INFO = android.;
public static final int WARN = android.util.Log.WARN;
public static final int ERROR = android.util.Log.ERROR;
public static final int ASSERT = android.util.Log.ASSERT;
private static LogNode mLogN
* Returns the next LogNode in the linked list.
public static LogNode getLogNode() {
return mLogN
* Sets the LogNode data will be sent to.
public static void setLogNode(LogNode node) {
mLogNode =
* Instructs the LogNode to print the log data provided. Other LogNodes can
* be chained to the end of the LogNode as desired.
* priority Log level of the data being logged. Verbose, Error, etc.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void println(int priority, String tag, String msg, Throwable tr) {
if (mLogNode != null) {
mLogNode.println(priority, tag, msg, tr);
* Instructs the LogNode to print the log data provided. Other LogNodes can
* be chained to the end of the LogNode as desired.
* priority Log level of the data being logged. Verbose, Error, etc.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged. The actual message to be logged.
public static void println(int priority, String tag, String msg) {
println(priority, tag, msg, null);
* Prints a message at VERBOSE priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void v(String tag, String msg, Throwable tr) {
println(VERBOSE, tag, msg, tr);
* Prints a message at VERBOSE priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void v(String tag, String msg) {
v(tag, msg, null);
* Prints a message at DEBUG priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void d(String tag, String msg, Throwable tr) {
println(DEBUG, tag, msg, tr);
* Prints a message at DEBUG priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void d(String tag, String msg) {
d(tag, msg, null);
* Prints a message at INFO priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void i(String tag, String msg, Throwable tr) {
println(INFO, tag, msg, tr);
* Prints a message at INFO priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void i(String tag, String msg) {
i(tag, msg, null);
* Prints a message at WARN priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void w(String tag, String msg, Throwable tr) {
println(WARN, tag, msg, tr);
* Prints a message at WARN priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void w(String tag, String msg) {
w(tag, msg, null);
* Prints a message at WARN priority.
* tag Tag for for the log data. Can be used to organize log statements.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void w(String tag, Throwable tr) {
w(tag, null, tr);
* Prints a message at ERROR priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void e(String tag, String msg, Throwable tr) {
println(ERROR, tag, msg, tr);
* Prints a message at ERROR priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void e(String tag, String msg) {
e(tag, msg, null);
* Prints a message at ASSERT priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void wtf(String tag, String msg, Throwable tr) {
println(ASSERT, tag, msg, tr);
* Prints a message at ASSERT priority.
* tag Tag for for the log data. Can be used to organize log statements.
* msg The actual message to be logged.
public static void wtf(String tag, String msg) {
wtf(tag, msg, null);
* Prints a message at ASSERT priority.
* tag Tag for for the log data. Can be used to organize log statements.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public static void wtf(String tag, Throwable tr) {
wtf(tag, null, tr);
内部包装了android的Log
Helper class which wraps Android's native Log utility in the Logger interface.
* normal DDMS output can be one of the many targets receiving and outputting logs simultaneously.
public class LogWrapper implements LogNode {
private LogNode mN
* Returns the next LogNode in the linked list.
public LogNode getNext() {
* Sets the LogNode data will be sent to..
public void setNext(LogNode node) {
* Prints data out to the console using Android's native log mechanism.
* priority Log level of the data being logged.
Verbose, Error, etc.
* tag Tag for for the log data.
Can be used to organize log statements.
* msg The actual message to be logged. The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public void println(int priority, String tag, String msg, Throwable tr) {
String useMsg =
if (useMsg == null) {
useMsg = "";
if (tr != null) {
msg += "\n" + Log.getStackTraceString(tr);
* 注意这里的Log是这个包下的package android.util
Log.println(priority, tag, useMsg);
if (mNext != null) {
mNext.println(priority, tag, msg, tr);
package com.mon.
* Basic interface for a logging system that can output to one or more targets.
* Note that in addition to classes that will output these logs in some format,
* one can also implement this interface over a filter and insert that in the chain,
* such that no targets further down see certain data, or see manipulated forms of the data.
* You could, for instance, write a "ToHtmlLoggerNode" that just converted all the log data
* it received to HTML and sent it along to the next node in the chain, without printing it
* anywhere.
public interface LogNode {
* Instructs first LogNode in the list to print the log data provided.
* @param priority Log level of the data being logged.
Verbose, Error, etc.
* @param tag Tag for for the log data.
Can be used to organize log statements.
* @param msg The actual message to be logged. The actual message to be logged.
* @param tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public void println(int priority, String tag, String msg, Throwable tr);
package com.mon.
除去一些用户并不关心的的数据
* Simple {@link LogNode} filter, removes everything except the message.
* Useful for situations like on-screen log output where you don't want a lot of metadata displayed,
* just easy-to-read message updates as they're happening.
public class MessageOnlyLogFilter implements LogNode {
LogNode mN
* Takes the "next" LogNode as a parameter, to simplify chaining.
* next The next LogNode in the pipeline.
public MessageOnlyLogFilter(LogNode next) {
public MessageOnlyLogFilter() {
public void println(int priority, String tag, String msg, Throwable tr) {
if (mNext != null) {
getNext().println(Log.NONE, null, msg, null);
* Returns the next LogNode in the chain.
public LogNode getNext() {
* Sets the LogNode data will be sent to..
public void setNext(LogNode node) {
最终执行输出Log代码,上边各种封装类都是作为消息传递chain:
展示Log的View
Simple TextView which is used to output log data received through the LogNode interface.
public class LogView extends TextView implements LogNode {
public LogView(Context context) {
super(context);
public LogView(Context context, AttributeSet attrs) {
super(context, attrs);
public LogView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
* Formats the log data and prints it out to the LogView.
* priority Log level of the data being logged.
Verbose, Error, etc.
* tag Tag for for the log data.
Can be used to organize log statements.
* msg The actual message to be logged. The actual message to be logged.
* tr If an exception was thrown, this can be sent along for the logging facilities
to extract and print useful information.
public void println(int priority, String tag, String msg, Throwable tr) {
String priorityStr = null;
switch(priority) {
case android.util.Log.VERBOSE:
priorityStr = "VERBOSE";
case android.util.Log.DEBUG:
priorityStr = "DEBUG";
case android.:
priorityStr = "INFO";
case android.util.Log.WARN:
priorityStr = "WARN";
case android.util.Log.ERROR:
priorityStr = "ERROR";
case android.util.Log.ASSERT:
priorityStr = "ASSERT";
String exceptionStr = null;
if (tr != null) {
exceptionStr = android.util.Log.getStackTraceString(tr);
final StringBuilder outputBuilder = new StringBuilder();
String delimiter = "\t";
appendIfNotNull(outputBuilder, priorityStr, delimiter);
appendIfNotNull(outputBuilder, tag, delimiter);
appendIfNotNull(outputBuilder, msg, delimiter);
appendIfNotNull(outputBuilder, exceptionStr, delimiter);
((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() {
public void run() {
appendToLog(outputBuilder.toString());
if (mNext != null) {
mNext.println(priority, tag, msg, tr);
public LogNode getNext() {
public void setNext(LogNode node) {
/** Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
* the logger takes so many arguments that might be null, this method helps cut out some of the
* agonizing tedium of writing the same 3 lines over and over.
* source StringBuilder containing the text to append to.
* addStr The String to append
* delimiter The String to separate the source and appended strings. A tab or comma,
for instance.
* The fully concatenated String as a StringBuilder
private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
if (addStr != null) {
if (addStr.length() == 0) {
delimiter = "";
return source.append(addStr).append(delimiter);
LogNode mN
/** Outputs the string as a new line of log data in the LogView. */
public void appendToLog(String s) {
append("\n" + s);
floatingactionbuttonbasic包代码分析:
说明:FloatingActionButton 这个View其实类似于一个CheckBox,当点击的时候记录当前的状态(选中或没选中),根据当期的状态来改变背景图片。背景图片是一个Selecter,状态改变自己会切换图片。这样就基本实现了FloatingActionButton 。但是,还没有让View悬浮起来。这个是5.0的一个新特性。及支持设置View在Z轴的位置。android:elevation这个属性就是设置Z轴位置的。当Z轴位置大于0时那么这个View就悬浮在其他View的上边了。
* A Floating Action Button is a {@link android.widget.Checkable} view distinguished by a circled
* icon floating above the UI, with special motion behaviors.
* 继承自FrameLayout,实现了Checkable接口
public class FloatingActionButton extends FrameLayout implements Checkable {
* Interface definition for a callback to be invoked when the checked state
* of a compound button changes.
public static interface OnCheckedChangeListener {
* Called when the checked state of a FAB has changed.
* @param fabView
The FAB view whose state has changed.
* @param isChecked The new checked state of buttonView.
void onCheckedChanged(FloatingActionButton fabView, boolean isChecked);
* An array of states.
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
private static final String TAG = "FloatingActionButton";
// A boolean that tells if the FAB is checked or not.
private boolean mC
// A listener to communicate that the FAB has changed it's state
private OnCheckedChangeListener mOnCheckedChangeL
public FloatingActionButton(Context context) {
this(context, null, 0, 0);
public FloatingActionButton(Context context, AttributeSet attrs) {
this(context, attrs, 0, 0);
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr);
setClickable(true);
// Set the outline provider for this view. The provider is given the outline which it can
// then modify as needed. In this case we set the outline to be an oval fitting the height
// and width.
//给这个View设置outline provider。这个provider提供的outline是可以改变的。在这种情况下我们这支这个边框为填充高度和宽度
setOutlineProvider(new ViewOutlineProvider() {
public void getOutline(View view, Outline outline) {
outline.setOval(0, 0, getWidth(), getHeight());
// Finally, enable clipping to the outline, using the provider we set above
//最后,设置一下使得outline可以点击
setClipToOutline(true);
* Sets the checked/unchecked state of the FAB.
* @param checked
public void setChecked(boolean checked) {
// If trying to set the current state, ignore.
if (checked == mChecked) {
mChecked =
// Now refresh the drawable state (so the icon changes)
refreshDrawableState();
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, checked);
* Register a callback to be invoked when the checked state of this button
* changes.
* @param listener the callback to call on checked state change
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener =
public boolean isChecked() {
public void toggle() {
setChecked(!mChecked);
* Override performClick() so that we can toggle the checked state when the view is clicked
* 当点击的时候会出发这个方法,super.performClick() 会抛出这个异常throw new RuntimeException("Stub!");打印Log
public boolean performClick() {
return super.performClick();
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// As we have changed size, we should invalidate the outline so that is the the
// correct size
invalidateOutline();
* @param extraSpace
如果不为extraSpace不为0,表示返回的int[]数组会在原始数组基础上添加额外的extraSpace个位置,在这些位置上你可以添加自己的一些额外信息
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates专门用来在onCreateDrawableState返回的数组上添加一个额外的属性
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
return drawableS
package com.example.android.float
import com.mon.logger.L
import android.app.A
import android.net.U
import android.os.B
import android.support.v4.app.F
import android.view.LayoutI
import android.view.V
import android.view.ViewG
这个Fragment将包含俩个FloatingActionButton,并监听点击事件。使用上边的Log包下的工具输出Log信息。
* This fragment inflates a layout with two Floating Action Buttons and acts as a listener to
* changes on them.
public class FloatingActionButtonBasicFragment extends Fragment implements FloatingActionButton.OnCheckedChangeListener{
private final static String TAG = "FloatingActionButtonBasicFragment";
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fab_layout, container, false);
FloatingActionButton fab1 = (FloatingActionButton) rootView.findViewById(R.id.fab_1);
fab1.setOnCheckedChangeListener(this);
FloatingActionButton fab2 = (FloatingActionButton) rootView.findViewById(R.id.fab_2);
fab2.setOnCheckedChangeListener(this);
return rootV
public void onCheckedChanged(FloatingActionButton fabView, boolean isChecked) {
switch (fabView.getId()){
case R.id.fab_1:
Log.d(TAG, String.format("FAB 1 was %s.", isChecked ? "checked" : "unchecked"));
case R.id.fab_2:
Log.d(TAG, String.format("FAB 2 was %s.", isChecked ? "checked" : "unchecked"));
package com.example.android.float
import android.os.B
import android.support.v4.app.FragmentT
import android.view.M
import android.view.MenuI
import android.widget.ViewA
import com.mon.activities.SampleActivityB
import com.mon.logger.L
import com.mon.logger.LogF
import com.mon.logger.LogW
import com.mon.logger.MessageOnlyLogF
* A simple launcher activity containing a summary sample description, sample log and a custom
* {@link android.support.v4.app.Fragment} which can display a view.
* For devices with displays with a width of 720dp or greater, the sample log is always visible,
* on other devices it's visibility is controlled by an item on the Action Bar.
public class MainActivity extends SampleActivityBase {
public static final String TAG = "MainActivity";
private boolean mLogS
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
FloatingActionButtonBasicFragment fragment = new FloatingActionButtonBasicFragment();
transaction.replace(R.id.sample_content_fragment, fragment);
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem logToggle = menu.findItem(R.id.menu_toggle_log);
logToggle.setVisible(findViewById(R.id.sample_output) instanceof ViewAnimator);
logToggle.setTitle(mLogShown ? R.string.sample_hide_log : R.string.sample_show_log);
return super.onPrepareOptionsMenu(menu);
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_toggle_log:
mLogShown = !mLogS
ViewAnimator output = (ViewAnimator) findViewById(R.id.sample_output);
if (mLogShown) {
output.setDisplayedChild(1);
output.setDisplayedChild(0);
supportInvalidateOptionsMenu();
return true;
return super.onOptionsItemSelected(item);
* Create a chain of targets that will receive log data
* 初始化Log工具
public void initializeLogging() {
LogWrapper logWrapper = new LogWrapper();
* Log的消息传递是依据一个链路依次传递的,Log传递到LogWrapper,LogWrapper传递到MessageOnlyLogFilter,MessageOnlyLogFilter传递到LogFragment
Log.setLogNode(logWrapper);
MessageOnlyLogFilter msgFilter = new MessageOnlyLogFilter();
logWrapper.setNext(msgFilter);
LogFragment logFragment = (LogFragment) getSupportFragmentManager()
.findFragmentById(R.id.log_fragment);
msgFilter.setNext(logFragment.getLogView());
Log.i(TAG, "Ready");
&?xml version="1.0" encoding="UTF-8"?&
android:orientation="vertical" xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" &
android:id="@+id/fab_1"
android:layout_width="@dimen/fab_size"
android:layout_height="@dimen/fab_size"
android:layout_marginTop="16dp"
android:elevation="@dimen/fab_elevation"
android:background="@drawable/fab_background"
android:stateListAnimator="@animator/fab_anim"
android:layout_gravity="center_horizontal"&
android:layout_width="@dimen/fab_icon_size"
android:layout_height="@dimen/fab_icon_size"
android:src="@drawable/fab_icons"
android:layout_gravity="center"
android:duplicateParentState="true"/&
android:id="@+id/fab_2"
android:layout_width="@dimen/fab_size_small"
android:layout_height="@dimen/fab_size_small"
android:layout_marginTop="128dp"
android:elevation="@dimen/fab_elevation"
android:background="@drawable/fab_background"
android:stateListAnimator="@animator/fab_anim"
android:layout_gravity="center_horizontal"&
android:layout_width="@dimen/fab_icon_size"
android:layout_height="@dimen/fab_icon_size"
android:src="@drawable/fab_icons"
android:layout_gravity="center"
android:duplicateParentState="true"/&
XML文件的预览效果:
RecyclerView
代码分析:
Log输出同FloatingActionButton完全相同。这里不再分析。
View的创建过程分析:
package com.example.android.
import android.os.B
import android.support.v4.app.F
import android.support.v7.widget.GridLayoutM
import android.support.v7.widget.LinearLayoutM
import android.support.v7.widget.RecyclerV
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.RadioB
* 使用Fragment加载一个RecyclerView
* Demonstrates the use of {@link RecyclerView} with a {@link LinearLayoutManager} and a
* {@link GridLayoutManager}.
public class RecyclerViewFragment extends Fragment {
private static final String TAG = "RecyclerViewFragment";
private static final String KEY_LAYOUT_MANAGER = "layoutManager";
private static final int SPAN_COUNT = 2;
private static final int DATASET_COUNT = 60;
private enum LayoutManagerType {
GRID_LAYOUT_MANAGER,
LINEAR_LAYOUT_MANAGER
protected LayoutManagerType mCurrentLayoutManagerT
protected RadioButton mLinearLayoutRadioB
protected RadioButton mGridLayoutRadioB
protected RecyclerView mRecyclerV
protected CustomAdapter mA
protected RecyclerView.LayoutManager mLayoutM
protected String[] mD
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDataset();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.recycler_view_frag, container, false);
rootView.setTag(TAG);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
if (savedInstanceState != null) {
mCurrentLayoutManagerType = (LayoutManagerType) savedInstanceState
.getSerializable(KEY_LAYOUT_MANAGER);
setRecyclerViewLayoutManager(mCurrentLayoutManagerType);
mAdapter = new CustomAdapter(mDataset);
mRecyclerView.setAdapter(mAdapter);
mLinearLayoutRadioButton = (RadioButton) rootView.findViewById(R.id.linear_layout_rb);
mLinearLayoutRadioButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setRecyclerViewLayoutManager(LayoutManagerType.LINEAR_LAYOUT_MANAGER);
mGridLayoutRadioButton = (RadioButton) rootView.findViewById(R.id.grid_layout_rb);
mGridLayoutRadioButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setRecyclerViewLayoutManager(LayoutManagerType.GRID_LAYOUT_MANAGER);
return rootV
* Set RecyclerView's LayoutManager to the one given.
* 设置recyclerView的布局管理
* layoutManagerType Type of layout manager to switch to.
public void setRecyclerViewLayoutManager(LayoutManagerType layoutManagerType) {
int scrollPosition = 0;
if (mRecyclerView.getLayoutManager() != null) {
scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
.findFirstCompletelyVisibleItemPosition();
switch (layoutManagerType) {
case GRID_LAYOUT_MANAGER:
mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT);
mCurrentLayoutManagerType = LayoutManagerType.GRID_LAYOUT_MANAGER;
case LINEAR_LAYOUT_MANAGER:
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
mLayoutManager = new LinearLayoutManager(getActivity());
mCurrentLayoutManagerType = LayoutManagerType.LINEAR_LAYOUT_MANAGER;
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.scrollToPosition(scrollPosition);
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putSerializable(KEY_LAYOUT_MANAGER, mCurrentLayoutManagerType);
super.onSaveInstanceState(savedInstanceState);
* Generates Strings for RecyclerView's adapter. This data would usually come
* from a local content provider or remote server.
* 生成数据
private void initDataset() {
mDataset = new String[DATASET_COUNT];
for (int i = 0; i & DATASET_COUNT; i++) {
mDataset[i] = "This is element #" +
&?xml version="1.0" encoding="UTF-8"?&
xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"&
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:checkedButton="@+id/linear_layout_rb"&
android:id="@+id/linear_layout_rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/linear_layout_manager"/&
android:id="@+id/grid_layout_rb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/grid_layout_manager"/&
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/&
package com.example.android.
import com.mon.logger.L
import android.support.v7.widget.RecyclerV
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.TextV
* Provide views to RecyclerView with data from mDataSet.
* 自定义的RecyclerView数据适配器
public class CustomAdapter extends RecyclerView.Adapter&CustomAdapter.ViewHolder& {
private static final String TAG = "CustomAdapter";
private String[] mDataS
* Provide a reference to the type of views that you are using (custom ViewHolder)
* 提供一个指向自定义View的应用
public static class ViewHolder extends RecyclerView.ViewHolder {
* 这里不只可以是textView还可以是其他的View
private final TextView textV
public ViewHolder(View v) {
v.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "Element " + getPosition() + " clicked.");
textView = (TextView) v.findViewById(R.id.textView);
public TextView getTextView() {
return textV
* Initialize the dataset of the Adapter.
dataSet String[] containing the data to populate views to be used by RecyclerView.
public CustomAdapter(String[] dataSet) {
mDataSet = dataS
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.text_row_item, viewGroup, false);
return new ViewHolder(v);
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.getTextView().setText(mDataSet[position]);
public int getItemCount() {
return mDataSet.
说明:为什么要使用RecyclerView
从效果上说,RecyclerView和ListView是差不多的,都是列表。
①但是RecyclerViwe支持多种布局方式,可以通过设置不同的布局方式实现不同效果,这一点比较灵活。
②直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
因为RecyclerView帮我们封装了Holder,所以我们自己写的ViewHolder就需要继承RecyclerView.ViewHolder,只有这样,RecyclerView才能帮你去管理这个ViewHolder类。
③以前的getView方法的渲染数据部分的代码相当于onBindViewHolder(),所以如果调用adapter.notifyDataSetChanged()方法,应该也会重新调用onBindViewHolder()方法才对吧?实验后,果然如此!
除了adapter.notifyDataSetChanged()这个方法之外,新的Adapter还提供了其他的方法,如下:
public final void notifyDataSetChanged()
public final void notifyItemChanged(int position)
public final void notifyItemRangeChanged(int positionStart, int itemCount)
public final void notifyItemInserted(int position)
public final void notifyItemMoved(int fromPosition, int toPosition)
public final void notifyItemRangeInserted(int positionStart, int itemCount)
public final void notifyItemRemoved(int position)
public final void notifyItemRangeRemoved(int positionStart, int itemCount)
第一个方法没什么好讲的,跟以前一样。
notifyItemChanged(int position),position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了,当然,因为ViewHolder是复用的,所以如果position在当前屏幕以外,也就不会回调了,因为没有意义,下次position滚动会当前屏幕以内的时候同样会调用onBindViewHolder()方法刷新数据了。其他的方法也是同样的道理。
public final void notifyItemRangeChanged(int positionStart, int itemCount),顾名思义,可以刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)。
public final void notifyItemInserted(int position),这个方法是在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义。
public final void notifyItemMoved(int fromPosition, int toPosition),这个方法是从fromPosition移动到toPosition为止的时候可以使用这个方法刷新
public final void notifyItemRangeInserted(int positionStart, int itemCount),显然是批量添加。
public final void notifyItemRemoved(int position),第position个被删除的时候刷新,同样会有动画。
public final void notifyItemRangeRemoved(int positionStart, int itemCount),批量删除。
ActivitySceneTransitionBasic(Activity场景切换)
要求:5.0系统
MainActivity
package com.example.android.activity
import com.squareup.picasso.P
import android.app.A
import android.content.I
import android.os.B
import android.support.v4.app.ActivityC
import android.support.v4.app.ActivityOptionsC
import android.support.v4.util.P
import android.view.V
import android.view.ViewG
import android.widget.AdapterV
import android.widget.BaseA
import android.widget.GridV
import android.widget.ImageV
import android.widget.TextV
* Our main Activity in this sample. Displays a grid of items which an image and title. When the
* user clicks on an item, {@link DetailActivity} is launched, using the Activity Scene Transitions
* framework to animatedly do so.
* 当用户点击Gridview的时候,会使用Activity Scene Transitions framework(activity 场景切换框架)动画启动DetailActivity。
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
private GridView mGridV
private GridAdapter mA
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.grid);
mGridView = (GridView) findViewById(R.id.grid);
mGridView.setOnItemClickListener(this);
mAdapter = new GridAdapter();
mGridView.setAdapter(mAdapter);
* Called when an item in the {@link android.widget.GridView} is clicked. Here will launch the
* {@link DetailActivity}, using the Scene Transition animation functionality.
public void onItemClick(AdapterView&?& adapterView, View view, int position, long id) {
Item item = (Item) adapterView.getItemAtPosition(position);
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra(DetailActivity.EXTRA_PARAM_ID, item.getId());
* Now create an {@link android.app.ActivityOptions} instance using the
* {@link ActivityOptionsCompat#makeSceneTransitionAnimation(Activity, Pair[])} factory
* 使用ActivityOptionsCompat#makeSceneTransitionAnimation(Activity, Pair[])工厂方法来创建一个ActivityOptions
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
new Pair&View, String&(view.findViewById(R.id.imageview_item),
DetailActivity.VIEW_NAME_HEADER_IMAGE),
new Pair&View, String&(view.findViewById(R.id.textview_name),
DetailActivity.VIEW_NAME_HEADER_TITLE));
ActivityCompat.startActivity(this, intent, activityOptions.toBundle());
* {@link android.widget.BaseAdapter} which displays items.
private class GridAdapter extends BaseAdapter {
public int getCount() {
return Item.ITEMS.
public Item getItem(int position) {
return Item.ITEMS[position];
public long getItemId(int position) {
return getItem(position).getId();
public View getView(int position, View view, ViewGroup viewGroup) {
if (view == null) {
view = getLayoutInflater().inflate(R.layout.grid_item, viewGroup, false);
final Item item = getItem(position);
ImageView image = (ImageView) view.findViewById(R.id.imageview_item);
Picasso.with(image.getContext()).load(item.getThumbnailUrl()).into(image);
TextView name = (TextView) view.findViewById(R.id.textview_name);
name.setText(item.getName());
package com.example.android.activity
* Represents an Item in our application. Each item has a name, id, full size image url and
* thumbnail url.
public class Item {
private static final String LARGE_BASE_URL = "/androiddevelopers/sample_data/activity_transition/large/";
private static final String THUMB_BASE_URL = "/androiddevelopers/sample_data/activity_transition/thumbs/";
public static Item[] ITEMS = new Item[]{
new Item("Flying in the Light", "Romain Guy", "flying_in_the_light.jpg"),
new Item("Caterpillar", "Romain Guy", "caterpillar.jpg"),
new Item("Look Me in the Eye", "Romain Guy", "look_me_in_the_eye.jpg"),
new Item("Flamingo", "Romain Guy", "flamingo.jpg"),
new Item("Rainbow", "Romain Guy", "rainbow.jpg"),
new Item("Over there", "Romain Guy", "over_there.jpg"),
new Item("Jelly Fish 2", "Romain Guy", "jelly_fish_2.jpg"),
new Item("Lone Pine Sunset", "Romain Guy", "lone_pine_sunset.jpg"),
public static Item getItem(int id) {
for (Item item : ITEMS) {
if (item.getId() == id) {
return null;
private final String mN
private final String mA
private final String mFileN
Item(String name, String author, String fileName) {
mFileName = fileN
public int getId() {
return mName.hashCode() + mFileName.hashCode();
public String getAuthor() {
public String getName() {
public String getPhotoUrl() {
return LARGE_BASE_URL + mFileN
public String getThumbnailUrl() {
return THUMB_BASE_URL + mFileN
跳转过来的第二个Activity
package com.example.android.activity
import com.squareup.picasso.P
import android.app.A
import android.os.B
import android.os.B
import android.support.v4.view.ViewC
import android.transition.T
import android.widget.ImageV
import android.widget.TextV
* Our secondary Activity which is launched from {@link MainActivity}. Has a simple detail UI
* which has a large banner image, title and body text.
public class DetailActivity extends Activity {
public static final String EXTRA_PARAM_ID = "detail:_id";
public static final String VIEW_NAME_HEADER_IMAGE = "detail:header:image";
public static final String VIEW_NAME_HEADER_TITLE = "detail:header:title";
private ImageView mHeaderImageV
private TextView mHeaderT
private Item mI
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details);
mItem = Item.getItem(getIntent().getIntExtra(EXTRA_PARAM_ID, 0));
mHeaderImageView = (ImageView) findViewById(R.id.imageview_header);
mHeaderTitle = (TextView) findViewById(R.id.textview_title);
* Set the name of the view's which will be transition to, using the static values above.
* This could be done in the layout XML, but exposing it via static variables allows easy
* querying from other Activities
* 使用上边定义的常亮设置前一个Activity中的View对应当前Activity中的那个View
*因为场景切换其实是这俩个Activity中的场景有连贯性,所以在2个activity切换过程中向做到View也看起来是连贯的
* 切换过来的效果,所以要做这样的对应关系。
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);
loadItem();
private void loadItem() {
mHeaderTitle.setText(getString(R.string.image_header, mItem.getName(), mItem.getAuthor()));
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.LOLLIPOP && addTransitionListener()) {
loadThumbnail();
loadFullSizeImage();
* Load the item's thumbnail image into our {@link ImageView}.
private void loadThumbnail() {
Picasso.with(mHeaderImageView.getContext())
.load(mItem.getThumbnailUrl())
.into(mHeaderImageView);
* Load the item's full-size image into our {@link ImageView}.
private void loadFullSizeImage() {
Picasso.with(mHeaderImageView.getContext())
.load(mItem.getPhotoUrl())
.noPlaceholder()
.into(mHeaderImageView);
* Try and add a {@link Transition.TransitionListener} to the entering shared element
* {@link Transition}. We do this so that we can load the full-size image after the transition
* has completed.
* true if we were successful in adding a listener to the enter transition
private boolean addTransitionListener() {
final Transition transition = getWindow().getSharedElementEnterTransition();
if (transition != null) {
transition.addListener(new Transition.TransitionListener() {
public void onTransitionEnd(Transition transition) {
loadFullSizeImage();
transition.removeListener(this);
public void onTransitionStart(Transition transition) {
public void onTransitionCancel(Transition transition) {
transition.removeListener(this);
public void onTransitionPause(Transition transition) {
public void onTransitionResume(Transition transition) {
return true;
return false;
语音辅助功能 BasicAccessibility
注意:需要打开Settings & Accessibility & TalkBack功能。当点击这按钮的时候会有提示语音。
下面是一个自定义的View,添加到XML中使用就可以。
package com.example.android.
import android.annotation.TargetA
import android.content.C
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.os.B
import android.util.AttributeS
import android.view.V
import android.view.accessibility.AccessibilityE
* 自定义控件的访问性(即与用户的交互)
* Custom view to demonstrate accessibility.
* 这个控件没有使用任何框架层的控件,因此不能自动的与用户进行交互。我们使用android.view.accessibility.AccessibilityEvent来给控件提供与系统交互的能力
* &p&This view does not use any framework widgets, so does not get any accessibility features
* automatically. Instead, we use {@link android.view.accessibility.AccessibilityEvent} to provide accessibility hints to
* 例如,如果把TalkBack设置成可以使用的,那么当用户讲话的时候就会收到这个Vie的反馈
* &p&For example, if TalkBack is enabled, users will be able to receive spoken feedback as they
* interact with this view.
* 更一般的,这个View有多个位置分别指向1到4.当每次拨号的时候,下一个位置将会被选中
* &p&More generally, this view renders a multi-position "dial" that can be used to select a value
* between 1 and 4. Each time the dial is clicked, the next position will be selected (modulo
* the maximum number of positions).
public class DialView extends View {
private static int SELECTION_COUNT = 4;
private static float FONT_SIZE = 40f;
private float mW
private float mH
private float mWidthP
private float mHeightP
private Paint mTextP
private Paint mDialP
private float mR
private int mActiveS
* 构造函数将会在加载XMl文件时被调用。
* Constructor that is called when inflating a view from XML. This is called
* when a view is being constructed from an XML file, supplying attributes
* that were specified in the XML file.
* &p&In our case, this constructor just calls init().
* 当前View所正在运行的上下文
* context The Context the view is running in, through which it can
access the current theme, resources, etc.
The attributes of the XML tag that is inflating the view.
public DialView(Context context, AttributeSet attrs) {
super(context, attrs);
* 初始化本地变量。
* Helper method to initialize instance variables. Called by constructor.
private void init() {
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(FONT_SIZE);
mDialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDialPaint.setColor(Color.GRAY);
mActiveSelection = 0;
* 当点击的时候调用SendAccessibilityEvent来生成一个AccessibilityEvents发送给系统。然而AccessibilityEvents
* 也是有类型的,具体选用什么类型取决于用户怎么个View交互。在这个例子中当用户点击View的时候View会改变选择的状态
* 因此,类型选择TYPE_VIEW_SELECTED而不是TYPE_VIEW_CLICKED
* 我们可以给AccessibilityEvent在onPopulateAccessibilityEvent()方法中添加更多的一些关于View状态的信息。
* 因为系统会为每一个AccessibilityEvent调用onPopulateAccessibilityEvent()方法
* 关于事件的接收:这里并没有对发出的事件进行处理。要想对事件处理必须实现AccessibilityService。例子参看
* /?post=26
*这个功能主要实现的是android里边的辅助功能。对于盲人点击屏幕的时候可能不知道点哪了。但是通过这种方式可以
* 方便的进行语音提示或者震动
setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mActiveSelection = (mActiveSelection + 1) % SELECTION_COUNT;
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
invalidate();
* This is where a View should populate outgoing accessibility events with its text content.
* While this method is free to modify event attributes other than text content, doing so
* should normally be performed in
* {@link #onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent)}.
* &p&Note that the behavior of this method will typically vary, depending on the type of
* accessibility event is passed into it. The allowed values also very, and are documented
* in {@link android.view.accessibility.AccessibilityEvent}.
* &p&Typically, this is where you'll describe the state of your custom view. You may also
* want to provide custom directions when the user has focused your view.
* event The accessibility event which to populate.
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
int eventType = event.getEventType();
* 通常情况下当方法执行到这里时表示用户已近和View发生了交互。但是传递过来的事件状态可能是改变的也可能是没有改变的
* 我们在这里添加一些其他的元数据但是没有收到反馈。但是这些数据可能被语音引擎使用
* 需要到设置里边打开服务才能听到声音。OK?
* To run this sample as intended you will need to turn on TalkBack (or another text to speach system)
on your Android device. Go to Settings & Accessibility & TalkBack to turn TalkBack on.
When you run the sample with TalkBack mode on, TalkBack will read aloud the
description of the in-focus widget.
if (eventType == AccessibilityEvent.TYPE_VIEW_SELECTED ||
eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
event.getText().add("Mode selected: " + Integer.toString(mActiveSelection + 1) + ".");
event.setItemCount(SELECTION_COUNT);
event.setCurrentItemIndex(mActiveSelection);
if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
event.getText().add("Tap to change.");
* 当View大小改变的时候调用。当View第一次被添加到一个视图结构中去的时候,掺入的参数oldw
* This is called during layout when the size of this view has changed. If
* you were just added to the view hierarchy, you're called with the old
* values of 0.
* 在这个方法里我们可以确定我们View的大小
* &p&This is where we determine the drawing bounds for our custom view.
Current width of this view.
Current height of this view.
* oldw Old width of this view.
* oldh Old height of this view.
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
float xPadding = (float) (getPaddingLeft() + getPaddingRight());
float yPadding = (float) (getPaddingTop() + getPaddingBottom());
mWidthPadded = w - xP
mHeightPadded = h - yP
mRadius = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);
* 绘制内容
* Render view content.
* 绘制一个灰色的外圆当做是拨号盘,再画一个小的圆当做是表盘刻度。表盘刻度额位置由mActiveSelection变量决定
* &p&We render an outer grey circle to serve as our "dial", and then render a smaller black
* circle to server as our indicator. The position for the indicator is determined based
* on mActiveSelection.
* canvas the canvas on which the background will be drawn
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(mWidth / 2, mHeight / 2, (float) mRadius, mDialPaint);
final float labelRadius = mRadius + 10;
for (int i = 0; i & SELECTION_COUNT; i++) {
float[] xyData = computeXYForPosition(i, labelRadius);
float x = xyData[0];
float y = xyData[1];
canvas.drawText(Integer.toString(i + 1), x, y, mTextPaint);
final float markerRadius = mRadius - 35;
float[] xyData = computeXYForPosition(mActiveSelection, markerRadius);
float x = xyData[0];
float y = xyData[1];
canvas.drawCircle(x, y, 20, mTextPaint);
* Compute the X/Y-coordinates for a label or indicator, given the position number and radius
* where the label should be drawn.
Zero based position index
* radius Radius where label/indicator is to be drawn.
* 2-element array. Element 0 is X-coordinate, element 1 is Y-coordinate.
private float[] computeXYForPosition(final int pos, final float radius) {
float[] result = new float[2];
Double startAngle = Math.PI * (9 / 8d);
Double angle = startAngle + (pos * (Math.PI / 4));
result[0] = (float) (radius * Math.cos(angle)) + (mWidth / 2);
result[1] = (float) (radius * Math.sin(angle)) + (mHeight / 2);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:7237次
排名:千里之外
原创:16篇
(4)(1)(10)(2)(1)(2)(2)

我要回帖

更多关于 系统升级win10 的文章

 

随机推荐