20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结

目录

  • 学习《Java和Android开发学习指南(第二版)》第35、36、37、38章——
  • 教材学习中的问题和解决过程
  • 代码调试中的问题和解决过程
  • 上周错题总结
  • [代码托管]
  • statistics.sh脚本运行结果的截图
  • 学习进度条
  • 参考资料

学习《Java和Android开发学习指南(第二版)》第35、36、37、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 运行其余程序代码。从用户的角度来看,应用程序的运行速度明显加快。
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第1张图片
4.GPU 与 CPU 性能比较?
理解 GPU 和 CPU 之间区别的一种简单方式是比较它们如何处理任务。CPU 由专为顺序串行处理而优化的几个核心组成,而 GPU 则拥有一个由数以千计的更小、更高效的核心(专为同时处理多重任务而设计)组成的大规模并行计算架构。
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第2张图片
35.3 创建一个定制视图
35.4 绘制基本形状
35.5 绘制文本
35.6 透明度
35.7 Shader
35.8 裁剪
35.9 使用路径
35.10 CanvasDemo应用程序
1.代码清单35.1 AndroidManifest.xml文件




    

    
        
            
                
                
            
        
    

2.代码清单35.2 CustomView类

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类

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);
    }

20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第3张图片
第36章片段
片段是能够嵌入到活动中的组件。和定制视图不同,片段有自己的生命周期,并且可以有,也可以没有用户界面。
36.1 片段的生命周期
1.Android四大组件的生命周期
(1)Service生命周期
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第4张图片
(2)Activity生命周期
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第5张图片
(3)片段生命周期
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第6张图片
(4)Activity与片段生命周期的对比
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第7张图片
片段所在的 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文件




    

    
        
            
                
                
            
        
    

2.代码清单36.2 主活动的布局文件


    
    

3.代码清单36.3 fragment_names.xml文件

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 adapter = new ArrayAdapter(
                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文件


    
    

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选项❤

20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第8张图片
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 adapter = new ArrayAdapter(
                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文件


    
    

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();
    }
}

20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第9张图片
第37章多面板布局
37.1 概览
如果要编写一个在两种类型的设备上显示得不错的应用程序,通常的策略是支持两种布局。可以对手机使用单面板的布局,而对平板电脑使用多面板的布局。
这里,dp表示独立的像素的密度。可以通过dp和屏幕密度(每英寸中的点的数目,或dpi)来计算像素数目。
px=dp*(dpi/160)
在Android3.2及其以后的版本中,使用一种新的技术,根据dp为单位的空间量来度量屏幕,而不是只使用4种屏幕大小,并试图让布局适应通用的大小分组。
37.2 多面板示例
1.代码清单37.1 AndroidManifest.xml文件




    
        
            
                

                
            
        
        
            
        
    

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文件(用于多面板)



    

    

    

4.代码清单37.4 fragment_item_detail.xml文件

5.代码清单37.5 res/layout/activity_item_list.xml file(用于单面板)

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(
                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;
    }
}

平板电脑——
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第10张图片
手机——
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第11张图片
第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的清单文件




    
        
            
                

                
            
        
    

2.代码清单38.2 activity_main.xml文件



    

        

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();
    }
}

20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第12张图片

教材学习中的问题和解决过程

  • 问题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计算的方法——
    20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第13张图片
  • 问题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)贪婪模式匹配过程分析
    20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第14张图片
    (2)非贪婪模式匹配过程分析
    20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第15张图片
    (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文件夹里运行。
20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结_第16张图片

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 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

参考资料

  • 《Java和Android开发学习指南(第二版)(Java for Android.2nd)》
  • Android Studio中文社区

你可能感兴趣的:(20189230杨 2018-2019-2 《移动平台开发实践》第9周学习总结)