揭秘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这个方法,我们需要根据是否向上还是向下显示相应的箭头,给用户一个很好的提示。

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

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

原文地址:https://www.cnblogs.com/manuosex/p/3613319.html