读书笔记

1.  Getting Started

1.1  Building YourFirst App

1.1.1  Createing anAndroid Project

1.1.2  Running YourApp

1.1.3  Building aSimple UI

以上三节没什么可说的

1.1.4  Start AnotherActivity

Android:textIsSelectable  //text view能否被长按选择

Layout_weight

editText.getText().toString()

getActionBar().setDisplayHomeAsUpEnabled(true);
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);//如果是4.1及其以上实际上没有必要作这一步的
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
<application ... >
    ...
    <activity
        android:name="com.example.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.example.myfirstapp.MainActivity" > //4.1及其以上,其实没有必要把类名写全
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.myfirstapp.MainActivity" />
    </activity>
</application>

Meta-data是老版本,而且必须在onOptionsItemSelected中处理

1.2  Adding theAction Bar

1.2.1  Setting UpThe Action Bar

3.0以上默认的主题是Theme.Holo,自带有actionbar

1.2.2  Adding ActionBar Buttons

Android:showAsAction=”ifRoom””never”

有些support lib里面定义的属性的namespace不是android:

 

1.2.3  Styling theAction Bar

Theme.Holo

Theme.Holo.Light

Theme.Holo.Light.DarkActionBar

ActionBar的客制化基本上是2级模式,第一级是继承自现有的某个theme,指定用一个style客制化theme中的一个属性,第二级是再定义1中的style,重写某个属性。当然也有更复杂的可能需要3级。

例如客制化action bar的background(如果要半透明的action bar就可以把background设置为半透明的图片。)

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@style/Theme.Holo.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/MyActionBar</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
           parent="@style/Widget.Holo.Light.ActionBar.Solid.Inverse">
        <item name="android:background">@drawable/actionbar_background</item>
    </style>
</resources>

然后把CustomActionBarTheme用在manifest中。

其他如文本颜色之类的也是类似。

android的theme可以去framework/base/core/res/res/values/theme.xml看,

根据这个XML里面的item再配合style.xml可以知道如何客制化。

1.2.4  Overlayingthe Action Bar

ActionBar的show()和hide()会导致activity因为resize而重新layout和重画,

如果想避免这种情况可以使用action bar的overlay mode,这样action bar浮在activity上面。

要overlay action,就客制化一个theme,设置android:windowActionBarOverlay为true

<resources>
    <!-- the theme applied to the application or activity -->
    <style name="CustomActionBarTheme"
           parent="@android:style/Theme.Holo">
        <item name="android:windowActionBarOverlay">true</item>
    </style>
</resources>

预留出action bar的高度

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?android:attr/actionBarSize">
    ...
</RelativeLayout>

1.3  SupportingDifferents Devices

1.3.1  SupportingDifferent Languages

1.3.2  SupportingDifferent Screens

1.3.3  SupportingDifferent Platform Version

Build.VERSION.SDK_INT;  Build.VERSION_CODES.JELLYBEAN

背景透明的activity

<activity android:theme="@android:style/Theme.Translucent">

 

1.4  Managing theActivity Lifecycle

没什么可说的

1.5  Building aDynamic UI with Fragment

没什么可说的

 

1.6  Saving Data

1.6.1  Saving K-VSets

SharedPreference指向一个包含KV对的文件

有两种方式得到SharedPreference,一是getSharedPreference()(context的方法),这种可以指定文件名字,用于有多个sharedPreference file的情况。而是getPreference,用于一个activity只有一个sharedPreference的情况。

 

每个app还有一个默认的perference文件用于保存setting,通过PreferenceManager可以拿到,PreferenceManager.getDefaultSharedPreferences(context);


编辑sharedPreference

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score), newHighScore);
editor.commit();

读取

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.string.saved_high_score_default);
long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);

Mode除了Context.MODE_PRIVATE之外还有MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE

 

1.6.2  Saving Files

Internal Storage:always是可用的;默认只属于某一个app(但如果你的mode不是private,其他app又知道你的具体文件路径,那他们还是能访问),其他app和user看不到;删除app时清空。

External Storage:有时不可用,当被mount时就不可用了;其他的pp和user可能读到里面的东西;卸载的时候有些可以删掉有些保留,取决于你用的API。

可以通过manifest中的android:installLocation属性设置app装到哪儿。

要向external storage中写东西需要申请权限android.permission.WRITE_EXTERNAL_STORAGE,(写权限暗含了读权限)向internalstorage中读写不需要申请权限。

 

保存文件到internal storage:

首先context提供两个方法getFilesDir()和getCacheDir(),返回这个app的internal存储的根目录(实际是data/data/package_name/files目录)和cache目录,每个app的internal storage都在固定位置,路径里面包含包名。

接下来File f = new File(context.getFilesDir(), “filename”)拿到file自己打开,或者直接使用context的方法openFileOutput(“filename”,MODE)直接拿到FileOutputStream,因为目录是固定的,所以只传入filename就可以。要在cache目录中创建临时文件:

File f = File.createTempFile(prefix,suffix, context.getCacheDir() )

 

保存文件到external storage:

首先确定外部存储是可用的,如果返回状态是MEDIA_MOUNT说明是OK的。

public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

接下来external storage中的文件分为两大类,一是public的,这种谁都能看到,删除app的时候也不删除,还有一种private,技术上也可能被其他人看到,但是删除app时会把这些文件删除。

对于前者使用

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

因为是public的,所以指定一个public的子目录便于管理,这个子目录可能不存在,可能需要你mkdirs。上面的方法代表的目录是mnt/sdcard/Pictures

对于后者使用

    File file = new File(context.getExternalFilesDir(
            Environment.DIRECTORY_PICTURES), albumName);

有些app喜欢直接在sdcard目录下创建自己的folder,可以通过Enviroment.getExternalStorageDirectory()拿到sdcard根目录。

总之file相关的方法集中在Enviroment和Context里面,用的时候查一下。

getFreeSpace(); getTotalSpace();context.deleteFile(“name”)删除internal storage中的文件。

 

1.6.3  Saving Datain SQL Database

创建contract class,定义和自己database相关的常量,例如URIs,表名,列名等等。一般把和整个database相关的信息定义在这个class的root级别,和每个table相关的定义如列名定义在内部类中。

 

1.7  InteractingWith Other Apps

1.7.1  Sending theUser to Another Activity

1.7.2  Getting aResult from the Activity

1.7.3  AllowingOther Apps to Start Your Activity

有些互斥的action不能写在同一个<intent-filer>里面,例如send和sendto

 

 

 

 

2  Content Shareing

2.1  Sharing SimplaeData

2.1.1  SendingSimplae Data to Other App

之前写过了

2.1.2  ReceivingSimple Data from Other App

没什么好写的

2.1.3  Adding andEasy Share Action

只需要在menu中添加一个item,actionProviderClass。

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
            android:id="@+id/menu_item_share"
            android:showAsAction="ifRoom"
            android:title="Share"
            android:actionProviderClass=
                "android.widget.ShareActionProvider" />
    ...
</menu>

然后设置一个share intent,需要在创建menu时拿到这个menu item,然后取出ShareActionProvider。之后可以在任意时刻call它的setShareIntent方法来设置intent,只要有activity可以处理这个intent,那么share就是可以点击的。(只写ACTION_SEND是不行的,想想intent filter的检查规则)

 

2.2  Sharing Files

把文件的content uri发给对方。

2.2.1  Setting UpFile Sharing

通过FileProvider提供file的content uri

2.2.2  Sharing aFile

2.2.3  Requesting aShared File

2.2.4  RetrievingFile Information

以上之前写过了

2.3  Sharing Fileswith NFC

2.3.1  Sending Filesto Another Devices

NFC现在有三种工作方式,一是读卡模式,读一些标签,这样系统读取后发出intent,然后你的activity可以声明处理这个intent。二是p2p模式,这种模式下两台设备都不能锁屏,发送方activity必须在前台,两台设备靠近时会出现”Touch to Beam” UI,点击后开始传输。三是刷卡模式,像工牌,公交卡这种。

本节讲一下第二种。

这种模式传输的文件必须放在external storage,然后必须是world-read模式,然后必须有uri,这种uri不能是FileProvider产生的content://这种uri。

在实现的时候要申请NFC权限和READ_EXTERNAL_STORAGE权限,以及声明NFC feature。

在使用的时候很简单,使用NfcAdapter.getDefaultAdapter(this),然后要么直接callNfcAdapter的setNdefPushMessage()方法把信息以NdefMessage的形式发出去,或者给NfcAdapter设置一个NfcAdapter.CreateBeamUrisCallback接口,实现里面的createBeamUris()方法。

2.3.2  ReceivingFiles from Another Devices

接收到的文件放在一个特殊的目录下,media scanner会scan这些文件,如果是媒体文件会加到media store provider中。

Copy完成后系统会发出一个notification,带有ACTION_Viewintent,还有第一个文件的mime type,指向第一个文件的uri。

然后可以声明activity处理这个intent。具体的处理就不写了。

 

 

3  Multimedia

3.1  Managing AudioPlayback

3.1.1  ControllingYour App’s Volume and Playback

3.1.2  ManagingAudio Focus

3.1.3  Dealing WithAudio Output Hardware

3.2  CapturingPhotos

3.2.1  Taking PhotosSimply

3.2.2  RecordingVideo Simply

3.2.3  Controllingthe Carema

以上除3.1.3和3.2.3都已经写过

3.3  PrintingContent

3.3.1  Photos

打印图片很简单,可以使用v4 support中的PrintHelper.

PrintHelper通过setScaleMode()方法设置模式,现在有两种模式:

SCALE_MODE_FIT:这个打印完整的图片,这样打印纸的边缘可能有空白

SCALE_MODE_FILL:这个填满所有的打印纸,因此图片的边缘可能打印不出来

无论哪种都保持宽高比例不变。

private void doPhotoPrint() {
    PrintHelper photoPrinter = new PrintHelper(getActivity());
    photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.droids);
    photoPrinter.printBitmap("droids.jpg - test print", bitmap);
}

如上就完事了,之后android print UI会出现,让用户选择打印机之类的,

3.3.2  HTML Document

把复杂的文档组织成HTML格式,然后用webview load本地的这个HTML,在onPageFinish中创建print job。

private void createWebPrintJob(WebView webView) {
    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getActivity()
            .getSystemService(Context.PRINT_SERVICE);
    // Get a print adapter instance
    PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();
    // Create a print job with name and adapter instance
    String jobName = getString(R.string.app_name) + " Document";
    PrintJob printJob = printManager.print(jobName, printAdapter,
            new PrintAttributes.Builder().build());
    // Save the job object for later status checking
    mPrintJobs.add(printJob);
}

app不需要发出notification,因为printframework会发出。

4. Graphics & Animations

4.1  DisplayingBitmaps Efficiently

4.1.1  Loading LargeBitmaps Efficiently

已经写过

4.1.2  ProcessingBitmaps Off the UI thread

对于不从memory中进行decode的图片,不要在UI thread中作decode操作。

对于list view和grid view,他们有很多子view,为了节省内存这些子view往往循环重复利用,因此如果针对一个子view启动AsyncTask,那么在AsyncTask执行完成时这个子view可能已经被回收了,所以要把子view和AsyncTask联系起来(BitmapDrawable),启动AsyncTask时如果发现这个view上已经有AsyncTask那就先把之前的AsyncTask cancel掉,然后启动新的AsyncTask.

4.1.3  CachingBitmaps

List view和grid view中可能有很多图片,当他们滚动出屏幕时会被回收,再滚动回来又会重新载入,所以为了效果流畅可以把图片cache在memory或者disk中。

要cache在memory中可以使用LruCache,它使用的是强引用类型的LinkedHashMap,当存储的东西达到上限时会把之前最久没有使用的释放掉。

LruCache<String, Bitmap> mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // 返回每个bitmap的大小,单位是k
            return bitmap.getByteCount() / 1024;
        }
    }; 

这样load完了就可以使用put方法缓存,再使用的时候就去里面get,和hash map是一样的。

Memory cache虽然速度快但是比较小,而且当你的activity被盖住后有可能被kill,这时候memorycache也被回收,所以也可以考虑使用disk cache,把bitmap缓存在文件(使用DiskLruCache)或者content provider中。

还有一种情况是configuration change,当activity被重建的时候重新load图片可能效果不好,这时候可以使用cache+fragment,fragment在自己的onCreate方法里面通过设置setRetainInstance(true)可以让这个fragment在activity的destory,re-careate过程(例如configurationchange流程)中被保持住。(这个fragment不能在back stack中)

 

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    RetainFragment retainFragment =
            RetainFragment.findOrCreateRetainFragment(getFragmentManager());//拿到某个fragment的实例,这些方法都不是重写的
    mMemoryCache = retainFragment.mRetainedCache;
    if (mMemoryCache == null) {
        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            ... // Initialize cache here as usual
        }
        retainFragment.mRetainedCache = mMemoryCache;
    }
    ...
}

class RetainFragment extends Fragment {
    private static final String TAG = "RetainFragment";
    public LruCache<String, Bitmap> mRetainedCache;//自己定义这个fragment要保存什么东西

    public RetainFragment() {}

    public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
        RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
        if (fragment == null) {
            fragment = new RetainFragment();
            fm.beginTransaction().add(fragment, TAG).commit();
        }
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);//设置fragment的保持属性,在activity的re-create过程中这个fragment实例是否被retain保持不变。
    }
}

4.1.4  ManagingBitmaps Memory

在2.3以后,如果LruCache满了,那么里面的bitmap会被移除,这时候可以把这个bitmap的软引用放到一个HashSet中(重写LruCache中的entryRemoved方法实现这个功能),这样在分配bitmap时可以先去这个Set中查一下看有没有大小合适的(在kk之前大小必须一致,在kk以及之后可以找一个比自己所需的bitmap更大的。),如果有就复用这个bitmap,这样可以省下分配回收bitmap的过程。

 

4.1.5  DisplayingBitmap in Your UI

如何显示在grid view就不用写了。

要使用ViewPager就要设置上一个FragmentStatePagerAdapter.

基本的实现是每张图片放进一个fragment,然后FragmentStatePagerAdapter中的callback会返回这些fragment并处理他们的状态,包含destory,save等等。

4.2  DisplayingGraphics with OpenGL ES

OpenGL ES API用于画一些3D图形,复杂的动画等等,能把这部分运算让GPU执行,这一部分暂时先没看

4.2.1—4.2.6

没看

 

 

 

 

 

 

 

 

 

 

7.  Interaction andEngagement

7.1  DesigningEffective Navigation

7.1.1—7.1.5全是design,不需要看

7.2  ImplementingEffective Navigation

 

 

 

 

 

8.  User Interface

8.1  Design forMultiple Screens

8.1.1  SupportingDifferent Screen Sizes

使用match_parent, wrap_content, relative layout而不要使用绝对位置绝对数值。

使用resource后缀,包括large,sw600dp,port等等。

使用nine patch图片(针对不同的屏幕比例)。

8.1.2  SupportingDifferent Screen Densities

对view大小使用dp,文字大小使用sp。

使用resource后缀,如xxhdpi

8.1.3  ImplementingAdaptive UI Flows

例如新闻app,大屏幕横屏时左边显示title list,右边显示content,其他情况下只显示title list或者content。

因为转屏时layout会变化,所以要明白自己当前在single-panel还是double-panel模式,可以通过check某个view id是否存在来决定。

8.2  Designing forTV

8.2.1—8.2.3没必要看

8.3  Creating CustomViews

8.3.1  Create aCustom View Class

提供一个如下的构造函数,这样才能用ADT调试

MyView(Context, AttributeSet)

{ super(c,s);}

 

定义view的客制化属性,创建文件 res/values/attrs.xml

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText"format="boolean"/>
       <attr name="labelPosition"format="enum">
           <enum name="left"value="0"/>
           <enum name="right"value="1"/>
       </attr>
   </declare-styleable>
</resources>

意思是给PieChart这个view创建两个客制化属性,一个是showText,boolean类型,另一个是lablePosition,enum类型可以取的值也列出来。

 

使用的时候定义自己的name space,最后那部分是自己的package name

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

 

对于定义在XML中的View,它的XML属性会通过AttributeSet进入View的构造方法

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);
   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

 

还可以在运行时改变这些属性,记得要invalidate(),如果size和shape有变化还要requestLayout()

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

 

8.3.2  ImplementCustome Drawing

要画出自己的view需要重写onDraw(Canvas c),Canvas本身有一些方法用于draw text,line,矩形,bitmap等等。还需要new 一个Paint,canvas定义画什么,例如圆形,矩形,Paint定义怎么画,例如什么颜色,是否填充等等。

如果画文字使用drawText(), Paint.setTypeFace()设置字体

画长方形等等使用drawRect(), drawOval(),drawArc()等等,使用paint的setStlye来设置是否填充等等。

复杂的形状使用Path,先创建Path后然后drawPath。(tabbar)

画图片drawBitmap,

使用LinearGradient来处理渐变。

 

确定画多大,一般来说View类有measurement方法,你自己的customer view只需重写onSizeChanged(入参是新的宽高和旧的宽高)就可以。在这里面计算一些和大小相关的东西。

       // Account for padding
       float xpad = (float)(getPaddingLeft() + getPaddingRight());
       float ypad = (float)(getPaddingTop() + getPaddingBottom());
       // Account for the label
       if (mShowText) xpad += mTextWidth;
       float ww = (float)w - xpad;
       float hh = (float)h - ypad;
       // Figure out how big we can make the pie.
       float diameter = Math.min(ww, hh);

还可以进一步实现onMeasure(),我感觉这个方法是要设定customer view的大小,onSizeChanged()是要设定customer view中要画的东西的大小,因为整个customer view的大小变了。

这个方法的入参告诉你这个parent希望你有多大,以及这是建议值还是硬性规定,如果重写这个方法最后要call setMeasuredDimension()来设置你计算的宽和高,不需要callsuper的实现。

 

8.3.3  Making the View Interactive

Customer view要和外部世界交互,可以重写onTouchEvent等方法,但是一般来说onTouchEvent自己没什么用,因为现代操作系统都是基于手势的,可以使用GestureDetector把touch event转换为手势。

接下来没有细看,是通过scroller这些类帮忙重写了onFling()这些方法,实现自己的手势效果,为了让UI流畅使用了动画。

 

8.3.4  Optimizing the View

去掉onDraw中的多余code,不要在onDraw中申请存储,减少调用invalidate和requestLayout。

减少ViewGroup层级。

可以使用硬件加速,但是硬件加速并不适用于所有app,或者app的所有部分。

可以在aplication级别,activity级别,window级别设置硬件加速,一般来说GPU适合于作 scaling, rotating, and translating bitmappedimages不适合作画直线曲线的操作,根据这个可以把某些view的layer type设置为View.LAYER_TYPE_HARDWARE,这样GPU把这个View以静态图片的形式cache在video memory,但是这个memory也很珍贵,所以也不要随便使用。

 

8.4  CreatingBackward Compatible UIs

如何使用新版本的组件和API让它跑在旧版本上。

8.4.1—8.4.4没看,总之就是抽象出新组件的API,然后用旧的内容再实现一次,在使用时用Build.VERSION.SDK_INT分开。

 

8.5  ImplementingAccessibility

8.5.1  Developing Accessible Applications

添加contentDescription;设计导航,就是XML里面那些android:nextFocusDown;

如果你使用android framework的UI组件,当你选中某个view或者focus变化时系统会发出一个accessibility event,accessibility service会接收到这个event做一些事情,例如读出contentDescription,所以当你实现自己的客制化view时最好也发出这种event。

 

8.5.2  Developing Accessible Services

就是如何实现上一节说的accessibility service,把用户选中组件的contentDescription读出来,或者进入某个区域提供震动反馈等等。

8.6  Managing theSystem UI

隐藏system bar(包含status bar和navigation bar)

8.6.1  Dimming the System Bar

设置flag就可以把system bar dim(适用于4.0以上),只是一些icon没了,bar还在

// This example uses decor view, but you can use any visible view.
View decorView = getActivity().getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView.setSystemUiVisibility(uiOptions);

当用户点击system bar时,system bar就自动恢复了,并且不再消失。

也可以用程序恢复

View decorView = getActivity().getWindow().getDecorView();
// Calling setSystemUiVisibility() with a value of 0 clears
// all flags.
decorView.setSystemUiVisibility(0);

8.6.2  Hiding the Status Bar

对4.1及其以后

和dim类似,也是setSystemUiVisibility,但是注意hide system bar之后最好也要把action bar隐藏。这个往下一拖status bar还会出来.

View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
// Remember that you should never show the action bar if the
// status bar is hidden, so hide that too if necessary.
ActionBar actionBar = getActionBar();
actionBar.hide();

要想让system bar显示出来需要清掉这个flag,如果离开了这个activity那么这个flag自动被清除掉,所以不要在onCreate里面设置,因为从后台切换回来的activity不会走onCreate。

 

还有一些其他flag让内容显示在status bar后面,显示在action bar后面,这些bar盖在内容的上层。

8.6.3  Hiding the Navigation Bar

基本上和8.6.2一样

 

8.6.4  Using Immersive Full-Screen Mode

SYSTEM_UI_FLAG_IMMERSIVE和SYSTEM_UI_FLAG_IMMERSIVE_STICKY

这种也可以和8.6.2 8.6.3结合进入全屏,但是如果用户点击原来system bar的位置时system bar就会再显示出来。

 

8.6.5  Responding to UI Visibility Changes

前面几节讲的设置的那些flag可能被清空,可以设置一个listener,当flag变化时会叫到这个listener中的callback

View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
        (new View.OnSystemUiVisibilityChangeListener() {
    @Override
    public void onSystemUiVisibilityChange(int visibility) {
        // Note that system bars will only be "visible" if none of the
        // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
        if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
            // TODO: The system bars are visible. Make any desired
            // adjustments to your UI, such as showing the action bar or
            // other navigational controls.
        } else {
            // TODO: The system bars are NOT visible. Make any desired
            // adjustments to your UI, such as hiding the action bar or
            // other navigational controls.
        }
    }
});

 

9. User Input

9.1  Using TouchGestures

让user和app通过触摸手势交互

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值