zoukankan      html  css  js  c++  java
  • 揭秘uc浏览器二

    这节,四个议题:

    ①一个网页显示在webview控件中

    ②如何正常隐藏显示标题栏。

    ③如何用runnable来隐藏标题栏,这样子就更加的专业化。

    ④上节我们说道了QuickActionGrid,看他长得怎么样。

    如何显示webview控件了,This is a question?这个除了上面的文章的支持外,主要是这个updateUI的方法。

    /**
         * Update the UI: Url edit text, previous/next button state,...
         */
        private void updateUI() {
            mUrlEditText.removeTextChangedListener(mUrlTextWatcher);
            mUrlEditText.setText(mCurrentWebView.getUrl());
            mUrlEditText.addTextChangedListener(mUrlTextWatcher);
            
            mPreviousButton.setEnabled(mCurrentWebView.canGoBack());
            mNextButton.setEnabled(mCurrentWebView.canGoForward());
            
            if (mCurrentWebView.getUrl() != null)
                mRemoveTabButton.setEnabled((mViewFlipper.getChildCount() > 1 || !mCurrentWebView.getUrl().equals(Constants.URL_ABOUT_START)));
            else
                mRemoveTabButton.setEnabled(mViewFlipper.getChildCount() > 1);
            
            mProgressBar.setProgress(mCurrentWebView.getProgress());
            
            updateGoButton();
            
            updateTitle();
            
            updateFavIcon();
        }
        

    这段代码是如此的熟悉,我们也来总结总结:

    ①我们需要更新URL文本框的数据,添加新的事件的监听。

    ②把前一步,后一步按钮设置是否禁用。

    ③把移去按钮,设置是否禁用。

    ④把进度条进度进行更新。

    ⑤更新去哪儿的按钮

    ⑥更新相应的标题

    ⑦更新相应的图标

    这个webview视图进行显示了,相应视图也进行更新了。

    如何正常显示标题栏,这个就是updateTitle方法做的事情,来瞧一瞧:

        /**
         * Update the application title.
         */
        private void updateTitle() {
            String value = mCurrentWebView.getTitle();
            
            if ((value != null) &&
                    (value.length() > 0)) {        
                this.setTitle(String.format(getResources().getString(R.string.ApplicationNameUrl), value));            
            } else {
                clearTitle();
            }
        }

    这是一个更新标题的方法,我们可以得出来相应总结,

    ①我们可以获取当前webview的标题,如果是标题不为空的话,我们就设置相应的标题。否则就清空标题.

    正常的隐藏标题栏,极大提高了用户体验,这是一个runnable接口功劳,那具体怎么做了:

     1 /**
     2      * Start a runnable to hide the tool bars after a user-defined delay.
     3      */
     4     private void startToolbarsHideRunnable() {
     5                         
     6         if (mHideToolbarsRunnable != null) {
     7             mHideToolbarsRunnable.setDisabled();
     8         }
     9         
    10         int delay = Integer.parseInt(Controller.getInstance().getPreferences().getString(Constants.PREFERENCES_GENERAL_BARS_DURATION, "3000"));
    11         if (delay <= 0) {
    12             delay = 3000;
    13         }
    14         
    15         mHideToolbarsRunnable = new HideToolbarsRunnable(this, delay);        
    16         new Thread(mHideToolbarsRunnable).start();
    17     }
    18     
    19     /**
    20      * Hide the tool bars.
    21      */
    22     public void hideToolbars() {
    23         if (mUrlBarVisible) {            
    24             if ((!mUrlEditText.hasFocus()) &&
    25                     (!mToolsActionGridVisible)) {
    26                 
    27                 if (!mCurrentWebView.isLoading()) {
    28                     setToolbarsVisibility(false);
    29                 }
    30             }
    31         }
    32         mHideToolbarsRunnable = null;
    33     }

    我这里能够得到这样的提示了:

    ①用到sharedpreference看用户设置时间,如果没有设置时间的话,默认是3秒就开启一条线程将其标题栏隐藏了。为什么会用到多线程了,这样不会更新主界面造成卡顿的现象。

    ②如果toolbar是隐藏的,就将其隐藏。

    QuickActionGrid是一个自定义控件,为什么用自定义控件了,

    ①android自带的控件太多bug。

    ②自定义控件也非常的灵活。

    源代码如下:

    public class QuickActionGrid extends QuickActionWidget {
    
    //    grid 控件
        private GridView mGridView;
    
        /**
         * grid 构造函数  数据的初始化
         * @param context  上下文对象
         */
        public QuickActionGrid(Context context) {
            super(context);
    
            setContentView(R.layout.gd_quick_action_grid);
    
            final View v = getContentView();
            mGridView = (GridView) v.findViewById(R.id.gdi_grid);
        }
        /**
         * 弹出相应的action的方法
         */
    
        @Override
        protected void populateQuickActions(final List<QuickAction> quickActions) {
    
            mGridView.setAdapter(new BaseAdapter() {
    
                public View getView(int position, View view, ViewGroup parent) {
    
                    TextView textView = (TextView) view;
    
                    if (view == null) {
                        final LayoutInflater inflater = LayoutInflater.from(getContext());
                        textView = (TextView) inflater.inflate(R.layout.gd_quick_action_grid_item, mGridView, false);
                    }
    
                    QuickAction quickAction = quickActions.get(position);
                    textView.setText(quickAction.mTitle);
                    textView.setCompoundDrawablesWithIntrinsicBounds(null, quickAction.mDrawable, null, null);
    
                    return textView;
    
                }
    
                public long getItemId(int position) {
                    return position;
                }
    
                public Object getItem(int position) {
                    return null;
                }
    
                public int getCount() {
                    return quickActions.size();
                }
            });
    
            mGridView.setOnItemClickListener(mInternalItemClickListener);
        }
    
        /**
         * 尺寸改变的事件
         */
        @Override
        protected void onMeasureAndLayout(Rect anchorRect, View contentView) {
    
            contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
                    LayoutParams.WRAP_CONTENT);
    
            int rootHeight = contentView.getMeasuredHeight();
    
            int offsetY = getArrowOffsetY();
            int dyTop = anchorRect.top;
            int dyBottom = getScreenHeight() - anchorRect.bottom;
    
            boolean onTop = (dyTop > dyBottom);
            int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY;
    
            setWidgetSpecs(popupY, onTop);
        }
    
        /**
         * 每项点击的事件
         */
        private OnItemClickListener mInternalItemClickListener = new OnItemClickListener() {
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                getOnQuickActionClickListener().onQuickActionClicked(QuickActionGrid.this, position);
                if (getDismissOnClick()) {
                    dismiss();
                }
            }
        };
    
    }

    这个quickGrid控件是继承与quickWidget控件,这也是一个自定义控件。对于他这个方法,我们集中于populateQuickActions方法和onMeasureAndLayout方法。

    ①populateQuickActions方法其实就是一个填充相应数据的方法,就是把相应的数据通过baseAdapter填充与gridview控件,gridview控件用于显示相应数据项。

    ②mInternalItemClickListener方法了,就是为每一个item赋予点击事件,如果这个点击动作已经执行以后,就相应弹出的popwindow就进行了隐藏。

    quickwidget控件在这个项目用的很多,这是许多控件的基类,怎么写的。

      1     private static final int MEASURE_AND_LAYOUT_DONE = 1 << 1;
      2 
      3     private final int[] mLocation = new int[2];
      4     private final Rect mRect = new Rect();
      5 
      6     private int mPrivateFlags;
      7 
      8     private Context mContext;
      9 
     10     private boolean mDismissOnClick;
     11     private int mArrowOffsetY;
     12 
     13     private int mPopupY;
     14     private boolean mIsOnTop;
     15 
     16     private int mScreenHeight;
     17     private int mScreenWidth;
     18     private boolean mIsDirty;
     19 
     20     private OnQuickActionClickListener mOnQuickActionClickListener;
     21     private ArrayList<QuickAction> mQuickActions = new ArrayList<QuickAction>();
     22 
     23     /**
     24      * Interface that may be used to listen to clicks on quick actions.
     25      *
     26      * @author Benjamin Fellous
     27      * @author Cyril Mottier
     28      */
     29     public static interface OnQuickActionClickListener {
     30         /**
     31          * Clients may implement this method to be notified of a click on a
     32          * particular quick action.
     33          *
     34          * @param position Position of the quick action that have been clicked.
     35          */
     36         void onQuickActionClicked(QuickActionWidget widget, int position);
     37     }
     38 
     39     /**
     40      * Creates a new QuickActionWidget for the given context.
     41      *
     42      * @param context The context in which the QuickActionWidget is running in
     43      */
     44     public QuickActionWidget(Context context) {
     45         super(context);
     46 
     47         mContext = context;
     48 
     49         initializeDefault();
     50 
     51         setFocusable(true);
     52         setTouchable(true);
     53         setOutsideTouchable(true);
     54         setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
     55         setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
     56 
     57         final WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
     58         mScreenWidth = windowManager.getDefaultDisplay().getWidth();
     59         mScreenHeight = windowManager.getDefaultDisplay().getHeight();
     60     }
     61 
     62     /**
     63      * Equivalent to {@link PopupWindow#setContentView(View)} but with a layout
     64      * identifier.
     65      *
     66      * @param layoutId The layout identifier of the view to use.
     67      */
     68     public void setContentView(int layoutId) {
     69         setContentView(LayoutInflater.from(mContext).inflate(layoutId, null));
     70     }
     71 
     72     private void initializeDefault() {
     73         mDismissOnClick = true;
     74         mArrowOffsetY = mContext.getResources().getDimensionPixelSize(R.dimen.gd_arrow_offset);
     75     }
     76 
     77     /**
     78      * Returns the arrow offset for the Y axis.
     79      *
     80      * @see {@link #setArrowOffsetY(int)}
     81      * @return The arrow offset.
     82      */
     83     public int getArrowOffsetY() {
     84         return mArrowOffsetY;
     85     }
     86 
     87     /**
     88      * Sets the arrow offset to a new value. Setting an arrow offset may be
     89      * particular useful to warn which view the QuickActionWidget is related to.
     90      * By setting a positive offset, the arrow will overlap the view given by
     91      * {@link #show(View)}. The default value is 5dp.
     92      *
     93      * @param offsetY The offset for the Y axis
     94      */
     95     public void setArrowOffsetY(int offsetY) {
     96         mArrowOffsetY = offsetY;
     97     }
     98 
     99     /**
    100      * Returns the width of the screen.
    101      *
    102      * @return The width of the screen
    103      */
    104     protected int getScreenWidth() {
    105         return mScreenWidth;
    106     }
    107 
    108     /**
    109      * Returns the height of the screen.
    110      *
    111      * @return The height of the screen
    112      */
    113     protected int getScreenHeight() {
    114         return mScreenHeight;
    115     }
    116 
    117     /**
    118      * By default, a {@link QuickActionWidget} is dismissed once the user
    119      * clicked on a {@link QuickAction}. This behavior can be changed using this
    120      * method.
    121      *
    122      * @param dismissOnClick True if you want the {@link QuickActionWidget} to
    123      * be dismissed on click else false.
    124      */
    125     public void setDismissOnClick(boolean dismissOnClick) {
    126         mDismissOnClick = dismissOnClick;
    127     }
    128 
    129     public boolean getDismissOnClick() {
    130         return mDismissOnClick;
    131     }
    132 
    133     /**
    134      * @param listener
    135      */
    136     public void setOnQuickActionClickListener(OnQuickActionClickListener listener) {
    137         mOnQuickActionClickListener = listener;
    138     }
    139 
    140     /**
    141      * Add a new QuickAction to this {@link QuickActionWidget}. Adding a new
    142      * {@link QuickAction} while the {@link QuickActionWidget} is currently
    143      * being shown does nothing. The new {@link QuickAction} will be displayed
    144      * on the next call to {@link #show(View)}.
    145      *
    146      * @param action The new {@link QuickAction} to add
    147      */
    148     public void addQuickAction(QuickAction action) {
    149         if (action != null) {
    150             mQuickActions.add(action);
    151             mIsDirty = true;
    152         }
    153     }
    154 
    155     /**
    156      * Removes all {@link QuickAction} from this {@link QuickActionWidget}.
    157      */
    158     public void clearAllQuickActions() {
    159         if (!mQuickActions.isEmpty()) {
    160             mQuickActions.clear();
    161             mIsDirty = true;
    162         }
    163     }
    164 
    165     /**
    166      * Call that method to display the {@link QuickActionWidget} anchored to the
    167      * given view.
    168      *
    169      * @param anchor The view the {@link QuickActionWidget} will be anchored to.
    170      */
    171     public void show(View anchor) {
    172 
    173         final View contentView = getContentView();
    174 
    175         if (contentView == null) {
    176             throw new IllegalStateException("You need to set the content view using the setContentView method");
    177         }
    178 
    179         // Replaces the background of the popup with a cleared background
    180         setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    181 
    182         final int[] loc = mLocation;
    183         anchor.getLocationOnScreen(loc);
    184         mRect.set(loc[0], loc[1], loc[0] + anchor.getWidth(), loc[1] + anchor.getHeight());
    185 
    186         if (mIsDirty) {
    187             clearQuickActions();
    188             populateQuickActions(mQuickActions);
    189         }
    190 
    191         onMeasureAndLayout(mRect, contentView);
    192 
    193         if ((mPrivateFlags & MEASURE_AND_LAYOUT_DONE) != MEASURE_AND_LAYOUT_DONE) {
    194             throw new IllegalStateException("onMeasureAndLayout() did not set the widget specification by calling"
    195                     + " setWidgetSpecs()");
    196         }
    197 
    198         showArrow();
    199         prepareAnimationStyle();
    200         showAtLocation(anchor, Gravity.NO_GRAVITY, 0, mPopupY);
    201     }
    202 
    203     protected void clearQuickActions() {
    204         if (!mQuickActions.isEmpty()) {
    205             onClearQuickActions();
    206         }
    207     }
    208 
    209     protected void onClearQuickActions() {
    210     }
    211 
    212     protected abstract void populateQuickActions(List<QuickAction> quickActions);
    213 
    214     protected abstract void onMeasureAndLayout(Rect anchorRect, View contentView);
    215 
    216     protected void setWidgetSpecs(int popupY, boolean isOnTop) {
    217         mPopupY = popupY;
    218         mIsOnTop = isOnTop;
    219 
    220         mPrivateFlags |= MEASURE_AND_LAYOUT_DONE;
    221     }
    222 
    223     private void showArrow() {
    224 
    225         final View contentView = getContentView();
    226         final int arrowId = mIsOnTop ? R.id.gdi_arrow_down : R.id.gdi_arrow_up;
    227         final View arrow = contentView.findViewById(arrowId);
    228         final View arrowUp = contentView.findViewById(R.id.gdi_arrow_up);
    229         final View arrowDown = contentView.findViewById(R.id.gdi_arrow_down);
    230 
    231         if (arrowId == R.id.gdi_arrow_up) {
    232             arrowUp.setVisibility(View.VISIBLE);
    233             arrowDown.setVisibility(View.INVISIBLE);
    234         } else if (arrowId == R.id.gdi_arrow_down) {
    235             arrowUp.setVisibility(View.INVISIBLE);
    236             arrowDown.setVisibility(View.VISIBLE);
    237         }
    238 
    239         ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams) arrow.getLayoutParams();
    240         param.leftMargin = mRect.centerX() - (arrow.getMeasuredWidth()) / 2;
    241     }
    242 
    243     private void prepareAnimationStyle() {
    244 
    245         final int screenWidth = mScreenWidth;
    246         final boolean onTop = mIsOnTop;
    247         final int arrowPointX = mRect.centerX();
    248 
    249         if (arrowPointX <= screenWidth / 4) {
    250             setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Left
    251                     : R.style.GreenDroid_Animation_PopDown_Left);
    252         } else if (arrowPointX >= 3 * screenWidth / 4) {
    253             setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Right
    254                     : R.style.GreenDroid_Animation_PopDown_Right);
    255         } else {
    256             setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Center
    257                     : R.style.GreenDroid_Animation_PopDown_Center);
    258         }
    259     }
    260 
    261     protected Context getContext() {
    262         return mContext;
    263     }
    264 
    265     protected OnQuickActionClickListener getOnQuickActionClickListener() {
    266         return mOnQuickActionClickListener;
    267     }

    首先这个控件本质是Popwindow,对于这个控件我们要探讨的有这么几点:

    ①show这个方法中了,主要是根据相应的锚基点来弹出来了,并且在指定的位置弹出相应的窗口。

    ②在showarrow这个方法,我们需要根据是否向上还是向下显示相应的箭头,给用户一个很好的提示。

    ③在动画的操作方法中,我们要根据其坐标是否小于全频宽度的四分之一位置,从左边的位置弹出来,其坐标从全频宽度四分之三的位置,从右侧位置弹出来了。

    有了这篇文章介绍,主界面应该了解了把?下节介绍收藏和历史界面。

  • 相关阅读:
    Learn Orleans 04
    Learn Orleans 03
    Learn Orleans 02
    Learn Orleans 01
    Python 导入 Excel 到数据库
    visio 2016/2019 时序图/序列图,修改消息的实线/虚线 箭头问题 返回消息状态
    steeltoe简单使用
    AOP in .NET
    centos 8 docker安装以及兼容性问题处理
    ef core SoftDelete Multi-tenancy 软删除、多租户实现 Global Query Filters
  • 原文地址:https://www.cnblogs.com/manuosex/p/3613319.html
Copyright © 2011-2022 走看看