20189230楊 2018-2019-2 《移動平臺開發實踐》第9周學習總結

學習《Java和Android開發學習指南(第二版)》第3五、3六、3七、38章——

第35章圖形和定製視圖
API(Application Programming Interface,應用程序編程接口)是一些預先定義的函數,目的是提供應用程序與開發人員基於某軟件或硬件得以訪問一組例程的能力,而又無需訪問源碼,或理解內部工做機制的細節。
35.2 硬件加速
1.什麼是GPU?
圖形處理器(英語:Graphics Processing Unit,縮寫:GPU),又稱顯示核心、視覺處理器、顯示芯片,是一種專門在我的電腦、工做站、遊戲機和一些移動設備(如平板電腦、智能手機等)上圖像運算工做的微處理器。
2.什麼是GPU加速計算?
GPU 加速計算是指同時利用圖形處理器 (GPU) 和 CPU,加快科學、分析、工程、消費和企業應用程序的運行速度。GPU 加速器於 2007 年由 NVIDIA® 率先推出,現已在世界各地爲政府實驗室、高校、公司以及中小型企業的高能效數據中心提供支持。GPU 可以使從汽車、手機和平板電腦到無人機和機器人等平臺的應用程序加速運行。
3.GPU如何加快軟件應用程序的應用速度?
GPU 加速計算能夠提供非凡的應用程序性能,能將應用程序計算密集部分的工做負載轉移到 GPU,同時仍由 CPU 運行其他程序代碼。從用戶的角度來看,應用程序的運行速度明顯加快。

4.GPU 與 CPU 性能比較?
理解 GPU 和 CPU 之間區別的一種簡單方式是比較它們如何處理任務。CPU 由專爲順序串行處理而優化的幾個核心組成,而 GPU 則擁有一個由數以千計的更小、更高效的核心(專爲同時處理多重任務而設計)組成的大規模並行計算架構。

35.3 建立一個定製視圖
35.4 繪製基本形狀
35.5 繪製文本
35.6 透明度
35.7 Shader
35.8 裁剪
35.9 使用路徑
35.10 CanvasDemo應用程序
1.代碼清單35.1 AndroidManifest.xml文件java

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.canvasdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="18" />

    <application
        android:hardwareAccelerated="false"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.canvasdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

2.代碼清單35.2 CustomView類android

package com.example.canvasdemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.view.View;

public class CustomView extends View {

    public CustomView(Context context) {
        super(context);
    }
    Paint paint = new Paint(Paint.FAKE_BOLD_TEXT_FLAG);
    Path starPath;
    Path curvePath;


    Paint textPaint = new Paint(Paint.LINEAR_TEXT_FLAG);
    Paint shaderPaint = new Paint();
    {
        Typeface typeface = Typeface.create(
                Typeface.SERIF, Typeface.BOLD);
        textPaint.setTypeface(typeface);
        Shader shader = new LinearGradient(0, 400, 300, 500,
                Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
        shaderPaint.setShader(shader);
        // create star path 
        starPath = createStarPath(300, 500);
        curvePath = createCurvePath();
    }

    protected void onDraw(Canvas canvas) {
        // draw basic shapes 
        canvas.drawLine(5,  5, 200, 5, paint);
        canvas.drawLine(5,  15, 200, 15, paint);
        canvas.drawLine(5,  25, 200, 25, paint);

        paint.setColor(Color.YELLOW);
        canvas.drawCircle(50, 70, 35, paint);

        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(100, 60, 150, 80), paint);

        paint.setColor(Color.DKGRAY);
        canvas.drawOval(new RectF(160, 60, 250, 80), paint);


        // draw text 
        textPaint.setTextSize(22);
        canvas.drawText("Welcome", 20, 150, textPaint);
        textPaint.setColor(Color.MAGENTA);
        textPaint.setTextSize(40);
        canvas.drawText("Welcome", 20, 190, textPaint);

        // transparency 
        textPaint.setColor(0xFF465574);
        textPaint.setTextSize(60);
        canvas.drawText("Android Rocks", 20, 340, textPaint);
        // opaque circle 
        canvas.drawCircle(80, 300, 20, paint);
        // semi-transparent circle 
        paint.setAlpha(110);
        canvas.drawCircle(160, 300, 39, paint);
        paint.setColor(Color.YELLOW);
        paint.setAlpha(140);
        canvas.drawCircle(240, 330, 30, paint);
        paint.setColor(Color.MAGENTA);
        paint.setAlpha(30);
        canvas.drawCircle(288, 350, 30, paint);
        paint.setColor(Color.CYAN);
        paint.setAlpha(100);
        canvas.drawCircle(380, 330, 50, paint);

        // draw text on path 
        textPaint.setColor(Color.rgb(155, 20, 10));
        canvas.drawTextOnPath("Nice artistic touches",
                curvePath, 10, 10, textPaint);


        // shader 
        canvas.drawRect(0, 400, 200, 500, shaderPaint);


        // create a star-shaped clip 
        canvas.drawPath(starPath, textPaint);
        textPaint.setColor(Color.CYAN);
        canvas.clipPath(starPath);
        textPaint.setColor(Color.parseColor("yellow"));
        canvas.drawText("Android", 350, 550, textPaint);
        textPaint.setColor(Color.parseColor("#abde97"));
        canvas.drawText("Android", 400, 600, textPaint);
        canvas.drawText("Android Rocks", 300, 650, textPaint);
        canvas.drawText("Android Rocks", 320, 700, textPaint);
        canvas.drawText("Android Rocks", 360, 750, textPaint);
        canvas.drawText("Android Rocks", 320, 800, textPaint);
    }

    private Path createStarPath(int x, int y) {
        Path path = new Path();
        path.moveTo(0 + x, 150 + y);
        path.lineTo(120 + x, 140 + y);
        path.lineTo(150 + x, 0 + y);
        path.lineTo(180 + x, 140 + y);
        path.lineTo(300 + x, 150 + y);
        path.lineTo(200 + x, 190 + y);
        path.lineTo(250 + x, 300 + y);
        path.lineTo(150 + x, 220 + y);
        path.lineTo(50 + x, 300 + y);
        path.lineTo(100 + x, 190 + y);
        path.lineTo(0 + x, 150 + y);
        return path;
    }

    private Path createCurvePath() {
        Path path = new Path();
        path.addArc(new RectF(400, 40, 780, 300),
                -210, 230);
        return path;
    }
}

3.代碼清單35.3 MainActivity類git

package com.example.canvasdemo;
import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        CustomView customView = new CustomView(this);
        setContentView(customView);
    }


第36章片斷
片斷是可以嵌入到活動中的組件。和定製視圖不一樣,片斷有本身的生命週期,而且能夠有,也能夠沒有用戶界面。
36.1 片斷的生命週期
1.Android四大組件的生命週期
(1)Service生命週期

(2)Activity生命週期

(3)片斷生命週期

(4)Activity與片斷生命週期的對比

片斷所在的 Activity 的生命週期會直接影響片斷的生命週期,其表現爲,Activity 的每次生命週期回調都會引起每一個片斷的相似回調。 例如,當 Activity 收到 onPause() 時,Activity 中的每一個片斷也會收到 onPause()。不過,片斷還有幾個額外的生命週期回調,用於處理與 Activity 的惟一交互,以執行構建和銷燬片斷 UI 等操做。 這些額外的回調方法是:
onAttach()
在片斷已與 Activity 關聯時調用(Activity 傳遞到此方法內)。
onCreateView()
調用它可建立與片斷關聯的視圖層次結構。
onActivityCreated()
在 Activity 的 onCreate() 方法已返回時調用。
onDestroyView()
在移除與片斷關聯的視圖層次結構時調用。
onDetach()
在取消片斷與 Activity 的關聯時調用。
圖示說明了受其宿主 Activity 影響的片斷生命週期流。在該圖中,您能夠看到 Activity 的每一個連續狀態如何決定片斷能夠收到的回調方法。 例如,當 Activity 收到其 onCreate() 回調時,Activity 中的片斷只會收到 onActivityCreated() 回調。
一旦 Activity 達到恢復狀態,您就能夠隨意向 Activity 添加片斷和移除其中的片斷。 所以,只有當 Activity 處於恢復狀態時,片斷的生命週期才能獨立變化。
不過,當 Activity 離開恢復狀態時,片斷會在 Activity 的推進下再次經歷其生命週期。
36.3 使用片斷
1.代碼清單36.1 FragmentDemo1的AndroidManifest.xml文件正則表達式

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragmentdemo1"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="com.example.fragmentdemo1.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

2.代碼清單36.2 主活動的佈局文件編程

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.fragmentdemo1.NamesFragment"
        android:id="@+id/namesFragment"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent" />
    <fragment android:name="com.example.fragmentdemo1.DetailsFragment"
        android:id="@+id/detailsFragment"
        android:layout_weight="2.5"
        android:layout_width="0dp"
        android:layout_height="match_parent" />
</LinearLayout>

3.代碼清單36.3 fragment_names.xml文件canvas

<ListView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
android:background="#FFFF55"/>

4.代碼清單36.4 NamesFragment類數組

package com.example.fragmentdemo1;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class NamesFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        final String[] names = {"Amsterdam", "Brussels", "Paris"};
        // use android.R.layout.simple_list_item_activated_1
        // to have the selected item in a different color
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                getActivity(),
                android.R.layout.simple_list_item_activated_1,
                names);

        View view = inflater.inflate(R.layout.fragment_names,
                container, false);
        final ListView listView = (ListView) view.findViewById(
                R.id.listView1);

        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setOnItemClickListener(new
                AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent,
                                            final View view, int position, long id) {
                        if (callback != null) {
                            callback.onItemSelected(names[position]);
                        }
                    }
                });
        listView.setAdapter(adapter);
        return view;
    }

    public interface Callback {
        public void onItemSelected(String id);
    }

    private Callback callback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof Callback) {
            callback = (Callback) activity;
        }
    }
    @Override
    public void onDetach() {
        super.onDetach();
        callback = null;
    }
}

5.代碼清單36.5 fragment_details.xml文件android-studio

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="#FAFAD2"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp"/>
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

6.代碼清單36.6 DetailsFragment類架構

package com.example.fragmentdemo1;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;

public class DetailsFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_details,
                container, false);
    }

    public void showDetails(String name) {
        TextView textView = (TextView)
                getView().findViewById(R.id.text1);
        textView.setText(name);

        ImageView imageView = (ImageView) getView().findViewById(
                R.id.imageView1);
        imageView.setScaleType(ScaleType.FIT_XY); // stretch image 
        if (name.equals("Amsterdam")) {
            imageView.setImageResource(R.drawable.amsterdam);
        } else if (name.equals("Brussels")) {
            imageView.setImageResource(R.drawable.brussels);
        } else if (name.equals("Paris")) {
            imageView.setImageResource(R.drawable.paris);
        }
    }
}

7.代碼清單36.7 FragmentDemo1的活動類

package com.example.fragmentdemo1;
import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity
        implements NamesFragment.Callback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public void onItemSelected(String value) {
        DetailsFragment details = (DetailsFragment)
                getFragmentManager().findFragmentById(
                        R.id.detailsFragment);
        details.showDetails(value);
    }
}
小嚐試:增添了一個Beijing選項❤


36.4 擴展ListFragment並使用FragmentManager
1.代碼清單36.8 NamesListFragment類

package com.example.fragmentdemo2;
import android.app.Activity;
import android.app.ListFragment;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

/* we don't need fragment_names-xml anymore */
public class NamesListFragment extends ListFragment {

    final String[] names = {"Amsterdam", "Brussels", "Paris"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                getActivity(),
                android.R.layout.simple_list_item_activated_1,
                names);
        setListAdapter(adapter);
    }

    @Override
    public void onViewCreated(View view,
                              Bundle savedInstanceState) {
        // ListView can only be accessed here, not in onCreate() 
        super.onViewCreated(view, savedInstanceState);
        ListView listView = getListView();
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setOnItemClickListener(new
                                                AdapterView.OnItemClickListener() {
                                                    @Override
                                                    public void onItemClick(AdapterView<?> parent,
                                                                            final View view, int position, long id) {
                                                        if (callback != null) {
                                                            callback.onItemSelected(names[position]);
                                                        }
                                                    }
                                                });

    }

    public interface Callback {
        public void onItemSelected(String id);
    }

    private Callback callback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof Callback) {
            callback = (Callback) activity;
        }
    }
    @Override
    public void onDetach() {
        super.onDetach();
        callback = null;
    }
}

2.代碼清單36.9 DetailsFragment類

package com.example.fragmentdemo2;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;

public class DetailsFragment extends Fragment {

    int imageId;
    String name;

    public DetailsFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments().containsKey("name")) {
            name = getArguments().getString("name");
        }
        if (getArguments().containsKey("imageId")) {
            imageId = getArguments().getInt("imageId");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(
                R.layout.fragment_details, container, false);
        TextView textView = (TextView)
                rootView.findViewById(R.id.text1);
        textView.setText(name);

        ImageView imageView = (ImageView) rootView.findViewById(
                R.id.imageView1);
        imageView.setScaleType(ScaleType.FIT_XY); //stretch image 
        imageView.setImageResource(imageId);
        return rootView;
    }
}

3.代碼清單36.10 activity_main.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment android:name="com.example.fragmentdemo2.NamesListFragment"
        android:id="@+id/namesFragment"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent"/>
    <FrameLayout
        android:id="@+id/details_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="2.5"/>
</LinearLayout>

4.代碼清單36.11 MainActivity類

package com.example.fragmentdemo2;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;

public class MainActivity extends Activity
        implements NamesListFragment.Callback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }
    @Override
    public void onItemSelected(String value) {

        Bundle arguments = new Bundle();
        arguments.putString("name", value);
        if (value.equals("Amsterdam")) {
            arguments.putInt("imageId", R.drawable.amsterdam);
        } else if (value.equals("Brussels")) {
            arguments.putInt("imageId", R.drawable.brussels);
        } else if (value.equals("Paris")) {
            arguments.putInt("imageId", R.drawable.paris);
        }
        DetailsFragment fragment = new DetailsFragment();
        fragment.setArguments(arguments);
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction fragmentTransaction =
                fragmentManager.beginTransaction();
        fragmentTransaction.replace(
                R.id.details_container, fragment);
        fragmentTransaction.commit();
    }
}


第37章多面板佈局
37.1 概覽
若是要編寫一個在兩種類型的設備上顯示得不錯的應用程序,一般的策略是支持兩種佈局。能夠對手機使用單面板的佈局,而對平板電腦使用多面板的佈局。
這裏,dp表示獨立的像素的密度。能夠經過dp和屏幕密度(每英寸中的點的數目,或dpi)來計算像素數目。
px=dp*(dpi/160)
在Android3.2及其之後的版本中,使用一種新的技術,根據dp爲單位的空間量來度量屏幕,而不是隻使用4種屏幕大小,並試圖讓佈局適應通用的大小分組。
37.2 多面板示例
1.代碼清單37.1 AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.multipanedemo" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".ItemListActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".ItemDetailActivity"
            android:label="@string/title_item_detail"
            android:parentActivityName=".ItemListActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value=".ItemListActivity" />
        </activity>
    </application>

</manifest>

2.代碼清單37.2 ItemListActivity類

package com.example.multipanedemo;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class ItemListActivity extends Activity
        implements ItemListFragment.Callbacks {

    private boolean twoPane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_item_list);

        if (findViewById(R.id.item_detail_container) != null) {
            twoPane = true;

            // In two-pane mode, list items should be given the
            // 'activated' state when touched.
            ((ItemListFragment) getFragmentManager()
                    .findFragmentById(R.id.item_list))
                    .setActivateOnItemClick(true);
        }
    }

    /**
     * Callback method from {@link ItemListFragment.Callbacks}
     * indicating that the item with the given ID was selected.
     */
    @Override
    public void onItemSelected(String id) {
        if (twoPane) {
            Bundle arguments = new Bundle();
            arguments.putString(ItemDetailFragment.ARG_ITEM_ID, id);
            ItemDetailFragment fragment = new ItemDetailFragment();
            fragment.setArguments(arguments);
            getFragmentManager().beginTransaction()
                    .replace(R.id.item_detail_container, fragment)
                    .commit();

        } else {
            // In single-pane mode, simply start the detail activity
            // for the selected item ID.
            Intent detailIntent = new Intent(this, ItemDetailActivity.class);
            detailIntent.putExtra(ItemDetailFragment.ARG_ITEM_ID, id);
            startActivity(detailIntent);
        }
    }
}

3.代碼清單37.3 res/layout-sw600dp/activity_item_list.xml文件(用於多面板)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:baselineAligned="false"
    android:divider="?android:attr/dividerHorizontal"
    android:orientation="horizontal"
    android:showDividers="middle"
    tools:context=".ItemListActivity">

    <!--
    This layout is a two-pane layout for the Items
    master/detail flow.
    
    -->

    <fragment android:id="@+id/item_list"
        android:name="com.example.multipanedemo.ItemListFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        tools:layout="@android:layout/list_content" />

    <FrameLayout android:id="@+id/item_detail_container"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3" />

</LinearLayout>

4.代碼清單37.4 fragment_item_detail.xml文件

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/item_detail"
    style="?android:attr/textAppearanceLarge"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:textIsSelectable="true"
    tools:context=".ItemDetailFragment" />

5.代碼清單37.5 res/layout/activity_item_list.xml file(用於單面板)

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/item_list"
    android:name="com.example.multipanedemo.ItemListFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    tools:context=".ItemListActivity"
    tools:layout="@android:layout/list_content" />

6.代碼清單37.6 ItemListFragment類

package com.example.multipanedemo;

import android.app.Activity;
import android.os.Bundle;
import android.app.ListFragment;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.example.multipanedemo.dummy.DummyContent;

public class ItemListFragment extends ListFragment {

    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    /**
     * The fragment's current callback object, which is notified of list item
     * clicks.
     */
    private Callbacks mCallbacks = sDummyCallbacks;

    /**
     * The current activated item position. Only used on tablets.
     */
    private int mActivatedPosition = ListView.INVALID_POSITION;

    /**
     * A callback interface that all activities containing this fragment must
     * implement. This mechanism allows activities to be notified of item
     * selections.
     */
    public interface Callbacks {
        /**
         * Callback for when an item has been selected.
         */
        public void onItemSelected(String id);
    }

    /**
     * A dummy implementation of the {@link Callbacks} interface that does
     * nothing. Used only when this fragment is not attached to an activity.
     */
    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(String id) {
        }
    };

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public ItemListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // TODO: replace with a real list adapter.
        setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(
                getActivity(),
                android.R.layout.simple_list_item_activated_1,
                android.R.id.text1,
                DummyContent.ITEMS));
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Restore the previously serialized activated item position.
        if (savedInstanceState != null
                && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }

        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        // Reset the active callbacks interface to the dummy implementation.
        mCallbacks = sDummyCallbacks;
    }

    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);

        // Notify the active callbacks interface (the activity, if the
        // fragment is attached to one) that an item has been selected.
        mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mActivatedPosition != ListView.INVALID_POSITION) {
            // Serialize and persist the activated item position.
            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
        }
    }

    /**
     * Turns on activate-on-click mode. When this mode is on, list items will be
     * given the 'activated' state when touched.
     */
    public void setActivateOnItemClick(boolean activateOnItemClick) {
        // When setting CHOICE_MODE_SINGLE, ListView will automatically
        // give items the 'activated' state when touched.
        getListView().setChoiceMode(activateOnItemClick
                ? ListView.CHOICE_MODE_SINGLE
                : ListView.CHOICE_MODE_NONE);
    }

    private void setActivatedPosition(int position) {
        if (position == ListView.INVALID_POSITION) {
            getListView().setItemChecked(mActivatedPosition, false);
        } else {
            getListView().setItemChecked(position, true);
        }

        mActivatedPosition = position;
    }
}

7.代碼清單37.7 ItemDetailFragment類

package com.example.multipanedemo;

import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


import com.example.multipanedemo.dummy.DummyContent;

/**
 * A fragment representing a single Item detail screen.
 * This fragment is either contained in a {@link ItemListActivity}
 * in two-pane mode (on tablets) or a {@link ItemDetailActivity}
 * on handsets.
 */
public class ItemDetailFragment extends Fragment {
    /**
     * The fragment argument representing the item ID that this fragment
     * represents.
     */
    public static final String ARG_ITEM_ID = "item_id";

    /**
     * The dummy content this fragment is presenting.
     */
    private DummyContent.DummyItem mItem;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public ItemDetailFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments().containsKey(ARG_ITEM_ID)) {
            // Load the dummy content specified by the fragment
            // arguments. In a real-world scenario, use a Loader
            // to load content from a content provider.
            mItem = DummyContent.ITEM_MAP.get(getArguments().getString(ARG_ITEM_ID));
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);

        // Show the dummy content as text in a TextView.
        if (mItem != null) {
            ((TextView) rootView.findViewById(R.id.item_detail)).setText(mItem.content);
        }

        return rootView;
    }
}

平板電腦——

手機——

第38章動畫
38.2 屬性動畫
38.2.1 Animator
設置目標對象;設置時長;啓動動畫
38.2.2 ValueAnimator
ValueAnimator經過計算一個從起始值向最終值過渡的一個值,從而建立動畫。
38.2.3 ObjectAnimator
38.2.4 AnimatorSet
以必定的順序播放一組動畫。
38.3 動畫項目
1.代碼清單38.1 AnimationDemo的清單文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.animationdemo" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.animationdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

2.代碼清單38.2 activity_main.xml文件

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/button1"
            android:text="@string/button_animate1"
            android:textColor="#ff4433"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="animate1"/>
        <Button
            android:id="@+id/button2"
            android:text="@string/button_animate2"
            android:textColor="#33ff33"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="animate2"/>
        <Button
            android:id="@+id/button3"
            android:text="@string/button_animate3"
            android:textColor="#3398ff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="animate3"/>

    </LinearLayout>
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|center"
        android:src="@drawable/photo1" />


</LinearLayout>

3.代碼清單38.3 MainActivity類

package com.example.animationdemo;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    public void animate1(View source) {
        View view = findViewById(R.id.imageView1);
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
                view, "rotationY", 0F, 720.0F);
        objectAnimator.setDuration(2000);
        objectAnimator.start();
    }

    public void animate2(View source) {
        final View view = findViewById(R.id.imageView1);
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0F,
                7200F);
        valueAnimator.setDuration(15000);

        valueAnimator.addUpdateListener(new
            ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Float value = (Float) animation.getAnimatedValue();
                    view.setRotationX(value);
                    if (value < 3600) {
                        view.setTranslationX(value/20);
                        view.setTranslationY(value/20);
                    } else {
                        view.setTranslationX((7200-value)/20);
                        view.setTranslationY((7200-value)/20);
                    }
                }
            });
        valueAnimator.start();
    }
    public void animate3(View source) {
        View view = findViewById(R.id.imageView1);
        ObjectAnimator objectAnimator1 =
                ObjectAnimator.ofFloat(view, "translationY", 0F,
                        300.0F);
        ObjectAnimator objectAnimator2 =
                ObjectAnimator.ofFloat(view, "translationX", 0F,
                        300.0F);
        objectAnimator1.setDuration(2000);
        objectAnimator2.setDuration(2000);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(objectAnimator1, objectAnimator2);

        ObjectAnimator objectAnimator3 =
                ObjectAnimator.ofFloat(view, "rotation", 0F,
                        1440F);
        objectAnimator3.setDuration(4000);
        animatorSet.play(objectAnimator3).after(objectAnimator2);
        animatorSet.start();
    }
}

教材學習中的問題和解決過程

  • 問題1:Android開發中dp、dpi、px的區別
  • 問題解決方案1:
    1.基本概念
    dp:安卓中的相對大小
    dpi:(dot per inch)每英寸像素多少
    px:像素點
    2.詳細說明
    (1)px和dpi
    px——
    日常所說的1920×1080只是像素數量,也就是1920px×1080px,表明手機高度上有1920個像素點,寬度上有1080個像素點。
    dpi——
    要想判別手機屏幕的顯示好壞,還要考慮屏幕的寬高(英寸),也就是用dpi即每英寸多少像素來評價屏幕的顯示效果。(否則假如手機分辨率是1920×1080,可是屏幕是幾十寸的,那顯示效果將不會很好,甚至你有可能看到小的像素塊,那將更影響視覺效果。)
    (2)dp
    dp的理解——
    其實dp就是爲了使得開發者設置的長度可以根據不一樣屏幕(分辨率/尺寸也就是dpi)得到不一樣的像素(px)數量。好比:我將一個控件設置長度爲1dp,那麼在160dpi上該控件長度爲1px,在240dpi的屏幕上該控件的長度爲1*240/160=1.5個像素點。
    也就是dp會隨着不一樣屏幕而改變控件長度的像素數量。
    dp計算的方法——
  • 問題2:視圖動畫與屬性動畫的區別
  • 問題解決方案2:
    視圖動畫早於屬性動畫,視圖動畫在API 1裏面就已經存在,屬性動畫直到API3.0纔出現,視圖動畫所在的包名爲android.view.animation,屬性動畫爲android.animation,可見視圖動畫只針對view起做用;試圖動畫中用到的類通常以Animation結尾,而屬性動畫則以Animator結尾。
    二者區別能夠總結以下:
    (1)屬性動畫比視圖動畫更強大,不但能夠實現縮放、平移等操做,還能夠本身定義動畫效果,監聽動畫的過程,在動畫過程當中或完成後作響應的動做。
    (2)屬性動畫不但能夠做用於View,還能做用於Object。
    (3)屬性動畫利用屬性的改變實現動畫,而視圖動畫僅僅改變了view的大小位置,但view真正的屬性沒有改變。

代碼調試中的問題和解決過程

  • 問題1:本週的課堂上,老師講解了正則表達式的相關內容,以後經過兩道課堂測試題考察了咱們對於知識的掌握程度,在這裏對正則表達式中貪婪模式和非貪婪模式的匹配過程加以總結概括。
  • 問題1解決方案:
    貪婪模式——是在整個表達式匹配成功的前提下,儘量多的去匹配量詞所修飾的字符。
    非貪婪模式——是在整個表達式匹配成功的前提下,儘量少的去匹配量詞所修飾的字符。
    它們之間的關係是:
    匹配優先量詞修飾的子表達式使用的是就是貪婪模式;
    忽略優先量詞修飾的子表達式使用的就是模式就是非貪婪模式;
    例如:要匹配的字符串爲'abcbd'
    貪婪模式正則表達式爲:a[bcd]b;非貪婪模式正則表達式爲:a[bcd]?b
    (1)貪婪模式匹配過程分析

    (2)非貪婪模式匹配過程分析

    (3)總結
    貪婪模式與非貪婪模式影響的是被量詞修飾的子表達式的匹配行爲,貪婪模式在整個表達式匹配成功的前提下,儘量多的匹配;非貪婪模式在整個表達式匹配成功的前提下,儘量少的匹配。另外,非貪婪模式只被部分NFA引擎所支持。從匹配效率上來看,能達到相同匹配結果時,貪婪模式的匹配效率一般會比較高,由於它回溯過程會比較少。

上週錯題總結

5.An array cannot hold object types.(數組中不能包含對象類型)
A .True
B .False
正確答案: B 個人答案: A
錯誤緣由:數組中能夠包含對象類型。
12.Which of the following method declarations correctly defines a method with a variable length parameter list?(下面哪一個方法聲明正肯定義了一個變長參數的方法)
A .public int average(int[] list)
B .public int average(int ... list)
C .public int average( ... )
D .public int average(int a, int b, int c, ...)
E .public int average(integers)
正確答案: B 個人答案: D
錯誤緣由:惟一具備有效語法的選項是選項A和選項B。選項A表示具備單個參數的方法聲明,該參數是對數組的引用。選項B正確地表示具備可變長度參數列表的方法的有效聲明。

[代碼託管]

https://gitee.com/EvelynYang/ninth_weeks

statistics.sh腳本運行結果的截圖

在新建的AndroidProjects文件夾中運行腳本,第六週及以前都是在IdeaProjects文件夾裏運行。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 200/200 2/2 20/20
第二週 300/500 1/3 18/38
第三週 500/1000 1/4 38/76
第四周 1000/2000 1/5 20/96
第五週 1000/3000 1/6 25/121
第六週 1000/4000 1/7 25/146
第七週 1000/5000 1/8 25/171
第八週 1000/6000 1/9 15/186
第九周 1000/7000 1/10 20/206

參考資料

相關文章
相關標籤/搜索