首页 > 代码库 > Android5.0开发范例大全 读书笔记(二)

Android5.0开发范例大全 读书笔记(二)

(二)用户交互

 2.1ActionBar

1.首先,调用onCreateOptionsMenu(Menu menu)方法为actionbar设置样式

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

  res/menu/support.xml如下

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_delete"
        android:icon="@android:drawable/ic_menu_delete"
        app:showAsAction="ifRoom"
        android:title="delete" />
    <item
        android:id="@+id/action_setting"
        android:showAsAction="never"
        android:orderInCategory="100"
        android:title="action_setting" />
</menu>

  接着,若Activity继承自AppCompatActivity,则调用代码

android.support.v7.app.ActionBar actionBar=getSupportActionBar();

  否则直接调用

ActionBar actionBar=getActionBar();

 2.2ToolBar

如今Google官方推荐使用Toolbar替代ActionBar

1.首先在XML中定义资源,要注意主题颜色,因为Toolbar默认不会自动继承当前material design的风格

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorAccent"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

  接着在代码中将toolbar集成

Toolbar toolbar= (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

 2.3动态方向锁定

1.通过setRequestedOrientation()方法实现,首先设置一个tooglebutton来设置是否锁定

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_orientation);
        toggleButton = (ToggleButton) findViewById(R.id.tb_orientation);
        assert toggleButton != null;
        if(getRequestedOrientation()!= ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED){
            toggleButton.setChecked(true);
        }else{
            toggleButton.setChecked(false);
        }
        toggleButton.setOnCheckedChangeListener(this);
    }

  接着在监听器中对屏幕方向进行动态的设置

@Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int current=getResources().getConfiguration().orientation;
        if(isChecked){
            switch (current){
                case Configuration.ORIENTATION_LANDSCAPE:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                    break;
                case Configuration.ORIENTATION_PORTRAIT:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                    break;
                default:
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
            }
        }else{
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        }
    }

 2.5创建上下文动作

 1.对于单个项相关上下文,使用PopupMenu

  首先自定义ContextListItem类以封装PopupMenu

public class ContextListItem extends LinearLayout implements PopupMenu.OnMenuItemClickListener, View.OnClickListener {

    private PopupMenu mPopupMenu;
    private TextView mTextView;
    public ContextListItem(Context context) {
        this(context,null);
    }

    public ContextListItem(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ContextListItem(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        String string=mTextView.getText().toString();
        switch (item.getItemId()){
            case R.id.action_delete:
                Toast.makeText(getContext(), "delete"+string,Toast.LENGTH_SHORT).show();
                break;
            case R.id.action_setting:
                Toast.makeText(getContext(), "edit"+string,Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mTextView= (TextView) findViewById(R.id.text);
        View contextButton=findViewById(R.id.context);
        contextButton.setOnClickListener(this);
        mPopupMenu=new PopupMenu(getContext(),contextButton);
        mPopupMenu.setOnMenuItemClickListener(this);
        mPopupMenu.inflate(R.menu.support);
    }

   其中,list_item.xml如下

<?xml version="1.0" encoding="utf-8"?>
<com.vastsum.joshua.android50.day20160927.ContextListItem xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/listPreferredItemHeightSmall"
    android:orientation="horizontal"
    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
    android:background="?android:attr/activatedBackgroundIndicator"
    >

    <TextView
        android:id="@+id/text"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:layout_weight="1"
        android:layout_gravity="center_vertical"/>

    <ImageView
        android:id="@+id/context"
        style="@style/Widget.AppCompat.Light.ActionButton.Overflow"
        android:layout_width="?android:attr/listPreferredItemHeightSmall"
        android:layout_height="match_parent"
        android:clickable="true"
        android:focusable="false" />
</com.vastsum.joshua.android50.day20160927.ContextListItem>

2.如果会影响多个项,则可以启用ActionMode来响应用户动作,下面展示二者相结合的完整代码

public class ActionActivity extends AppCompatActivity implements AbsListView.MultiChoiceModeListener {
    private static final String[] ITEMS = {"MOM", "DAD", "MOM", "DAD", "MOM", "DAD", "MOM", "DAD", "MOM", "DAD"};
    private ListView mList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mList = new ListView(this);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, R.id.text, ITEMS);
        mList.setAdapter(adapter);
        mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        mList.setMultiChoiceModeListener(this);
        setContentView(mList, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            startActionMode(ActionActivity.this);
        }
    });
    }

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
        int count = mList.getCheckedItemCount();
        mode.setTitle(String.format("%d Select", count));
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.support, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return true;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {

    }

}

2.8自定义BACK键

1.之前实现返回功能都是直接调用activity的finish()方法,现在发现可以调用

super.onBackPressed()

2.在默认情况下,UI中添加Fragment的操作不会再任务的回退栈中添加相应的Fragment,因此back键不能回退。

  因此,首先要通过FragmentTransaction的addToBackStack()方法将fragment添加到回退栈

ft=getFragmentManager().beginTransaction();
        ft.add(R.id.fl, MyFragment.newInstance("Second"));
        ft.addToBackStack("Second");
        ft.commit();

  接着调用FragmentTransaction的popBackStack()方法将fragment弹出

public void back(View view) {
        getFragmentManager().popBackStack();
    }

  顺便复习一下fragment的用法

 public static class MyFragment extends Fragment{
        private String title;
        public static MyFragment newInstance(String title){
            MyFragment fragment= new MyFragment();
            fragment.setTitle(title);
            return fragment;
        }

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            TextView textView=new TextView(getActivity());
            textView.setText(title);
            return textView;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_back);
        ft = getFragmentManager().beginTransaction();
        ft.add(R.id.fl, MyFragment.newInstance("First"));
        ft.commit();
    }

2.10监控TextView的变动

1.创建一个Watcher实现TextWatcher接口

public class CurrencyTextWatcher implements TextWatcher {
    boolean mEditing;

    public CurrencyTextWatcher() {
        mEditing = false;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public synchronized void afterTextChanged(Editable s) {
        if (!mEditing) {
            mEditing = true;
            String digits = s.toString().replaceAll("\\D", "");
            NumberFormat nf = NumberFormat.getCurrencyInstance();
            try {
                String formatted = nf.format(Double.parseDouble(digits) / 100);
                s.replace(0, s.length(), formatted);
            } catch (NumberFormatException n) {
                s.clear();
            }
            mEditing = false;
        }
    }
}

2.在Activity中设置Watcher监听

editText.addTextChangedListener(new CurrencyTextWatcher());

2.12消除软键盘

1.在特定的用户信息录入界面很有用处

 public void hide(View view) {
        InputMethodManager imm= (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(),0);
    }

2.13处理复杂的触摸事件

  talk is cheap ,show you the code!

1.实现自定义的一个scrollview

public class PanGestureScrollView extends FrameLayout {
    private GestureDetector mDetector;
    private Scroller mScroller;

    private float mInitialX, mInitialY;

    private int mTouchSlop;


    public PanGestureScrollView(Context context) {
        this(context, null);
    }


    public PanGestureScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PanGestureScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {

        mDetector = new GestureDetector(context, mListener);
        mScroller = new Scroller(context);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

    }

    @Override
    protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
        int childWidthMeasureSpec;
        int childHeightMeasureSpec;
        childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

    }

    @Override
    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
        final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

    }

    private GestureDetector.SimpleOnGestureListener mListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
            }
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            fling((int) -velocityX / 3, (int) -velocityY / 3);
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            scrollBy((int) distanceX, (int) distanceY);
            return true;
        }
    };

    private void fling(int i, int i1) {
        if (getChildCount() > 0) {
            int height = getHeight() - getPaddingBottom() - getPaddingTop();
            int width = getWidth() - getPaddingLeft() - getPaddingRight();
            int bottom = getChildAt(0).getHeight();
            int right = getChildAt(0).getWidth();
            mScroller.fling(getScrollX(), getScrollY(), i, i1, 0, Math.max(0, right - width), 0, Math.max(0, bottom - height));
            invalidate();
        }
    }

    private int clamp(int n, int my, int child) {
        if (my >= child || n < 0) {
            return 0;
        }
        if ((my + n) > child) {
            return child - my;
        }
        return n;
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            int oldX = getScrollX();
            int oldY = getScrollY();
            int x = mScroller.getCurrX();
            int y = mScroller.getCurrY();
            if (getChildCount() > 0) {
                View child = getChildAt(0);
                x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth());
                y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), child.getHeight());
                if (x != oldX || y != oldY) {
                    scrollTo(x, y);
                }
            }

        }
        postInvalidate();
    }

    @Override
    public void scrollTo(int x, int y) {
        if(getChildCount()>0){
            View child=getChildAt(0);
            x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth());
            y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), child.getHeight());
            if(x!=getScrollX()||y!=getScrollY()){
                super.scrollTo(x,y);
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                mInitialX=ev.getX();
                mInitialY=ev.getY();
                mDetector.onTouchEvent(ev);
                break;
            case MotionEvent.ACTION_MOVE:
                final float x=ev.getX();
                final float y=ev.getY();
                final int yDiff= (int) Math.abs(y-mInitialY);
                final int xDiff= (int) Math.abs(x-mInitialX);
                if(yDiff>mTouchSlop||xDiff>mTouchSlop){
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDetector.onTouchEvent(event);
    }
}

 

Android5.0开发范例大全 读书笔记(二)