Android5.0開發範例大全 讀書筆記(二)

(二)用戶交互android

 2.1ActionBargit

1.首先,調用onCreateOptionsMenu(Menu menu)方法爲actionbar設置樣式app

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

  res/menu/support.xml以下ide

<?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,則調用代碼post

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

  不然直接調用this

ActionBar actionBar=getActionBar();

 2.2ToolBarspa

現在Google官方推薦使用Toolbar替代ActionBarcode

1.首先在XML中定義資源,要注意主題顏色,由於Toolbar默認不會自動繼承當前material design的風格orm

<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集成xml

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);
    }
}
相關文章
相關標籤/搜索