view 相关代码片段笔记

代码中动态创建view,并把AttributeSet加入到当前自定义的view中,动态创建属性相关

 //https://blog.csdn.net/chenhuakang/article/details/53584429
    public static AttributeSet getAttribute(Context ctx,int layoutId){
        XmlPullParser parser = null;
        AttributeSet attributes = null;
        int type;
        try{
            parser = ctx.getResources().getXml(layoutId);//R.layout.textview
            attributes = Xml.asAttributeSet(parser);
            while ((type = parser.next()) != XmlPullParser.START_TAG &&
                    type != XmlPullParser.END_DOCUMENT) {
                // Empty
            }

            if (type != XmlPullParser.START_TAG) {
                throw new InflateException(parser.getPositionDescription()
                        + ": No start tag found!");
            }
        }catch (Resources.NotFoundException e){
            throw new IllegalArgumentException("xml file not found error!");
        }
        catch (XmlPullParserException e) {
            InflateException ex = new InflateException(e.getMessage());
            ex.initCause(e);
            throw ex;
        } catch (IOException e) {
            InflateException ex = new InflateException(
                    parser.getPositionDescription()
                            + ": " + e.getMessage());
            ex.initCause(e);
            throw ex;
        }
        return attributes;
    }

使用:

 AttributeSet attr =  ViewsHelper.getAttribute(act, R.layout.template_setitem);
            SettingItemCommon commonSettingItem = new SettingItemCommon(act,attr);
            commonSettingItem.setItemContent(item.name,item.desc,true);

Recycleview属性分割线处理

public static void initRecycleViewParams(RecyclerView rl,boolean needDivide){
        LinearLayoutManager layoutMag = new LinearLayoutManager(AppAppliacation.getAppContext());
        layoutMag.setOrientation(LinearLayoutManager.VERTICAL);
        rl.setLayoutManager(layoutMag);

        if(needDivide) {
            DividerItemDecoration divider = new DividerItemDecoration(rl.getContext(), DividerItemDecoration.VERTICAL);
            divider.setDrawable(ContextCompat.getDrawable(rl.getContext(), R.drawable.divider2));
            rl.addItemDecoration(divider);
        }
    }

绘图内容在padding外显示(默认为内部)

clipToPadding就是说控件的绘制区域是否在padding里面的
clipChildren是指子控件是否超过padding区域
两个属性设置了false那么这样子控件就能画到padding的区域了。

 获取activity contentview视图

activity.findViewById(Window.ID_ANDROID_CONTENT)

or

// Hijack the decorview
		ViewGroup decorView = (ViewGroup)activity.getWindow().getDecorView();
		View oldScreen = decorView.getChildAt(0);
		decorView.removeViewAt(0);

		// Setup the slider panel and attach it to the decor
		SliderPanel panel = new SliderPanel(activity, oldScreen, config);
		panel.setId(R.id.slidable_panel);
		oldScreen.setId(R.id.slidable_content);
		panel.addView(oldScreen);
		decorView.addView(panel, 0);

  

 viewTree绘制状态监听:

(1)ViewTreeObserver实现

final ViewTreeObserver observer = layoutContainer.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //判断ViewTreeObserver 是否alive,如果存活的话移除这个观察者
                if(observer.isAlive()){
                    observer.removeOnGlobalLayoutListener(this);
                    int viewWidth=view.getMeasuredWidth();
                    int viewHeight=view.getMeasuredHeight();
                }
            }
        });
        observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
            @Override
            public void onDraw() {
                if(observer.isAlive()){
                    observer.removeOnDrawListener(this);
                }
            }
        });

 (2)Choreographer方式:

@Override
    protected void onResume() {
        super.onResume();
        Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                start = SystemClock.uptimeMillis();
                log("绘制开始:height = "+view.getHeight());
            }
        });
    }

在activity中获取fragment中的控件
 getFragmentManager().findFragmentById(id).getView().findViewById(id)

EditText click事件无反应问题,

原因:touch事件影响 OnTouch -> OnFocusChange -> OnClick.

解决:使用TouchListener替换Click事件

edit.setOnTouchListener(new View.OnTouchListener() {//click事件处理
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if(MotionEvent.ACTION_UP == event.getAction()){
                        if(null!=changeLayout)
                            changeLayout.setVisibility(View.GONE);
                    }
                    return false;//注意返回
                }
            });

 自定义处理focus:

禁用 android:focusable="false"

设置focusListener

//            edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {//焦点处理
//                @Override
//                public void onFocusChange(View v, boolean hasFocus) {
//                    if(hasFocus)
//                        Toast.makeText(getApplicationContext(), "onFocusChange", Toast.LENGTH_LONG).show();
//                }
//            });

实现AutoCompleteTextView,SearchView功能

使用Listview+EditTextview+Filter Adatpter

1,Filter Adatpter处理

package com.bjzjkj.net.deviceapp.simcard_module.adapter;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.bjzjkj.net.deviceapp.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yudajun on 2017/6/16.
 * 弹出框下拉样式
 */

public class CommonPopviewListAdapter extends BaseAdapter {

    private Context mContext;
    private List<CommonItemModel> sunItems ,filteredData ;

    public CommonPopviewListAdapter(Context mContext,List<CommonItemModel> items) {
        this.mContext = mContext;
        this.sunItems = items;
        this.filteredData = items;
    }

    public void setData(List<CommonItemModel> items){
        this.sunItems = items;
        this.filteredData = items;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        HolderView holderView;
        // Important to not just null check, but rather to a instanceof
        // since we might get any subclass of view here.
        if (convertView instanceof HolderView) {
            holderView = (HolderView) convertView;
        } else {
            holderView = new HolderView(mContext, null);
        }
        holderView.bindData(filteredData.get(position).text);
        return holderView;
    }

    @Override
    public int getCount() {
        return filteredData.size();
    }

    @Override
    public CommonItemModel getItem(int position) {
        return filteredData.get(position);
    }

    @Override
    public long getItemId(int id) {
        return id;
    }

    private ItemFilter mFilter = new ItemFilter();

    public Filter getFilter() {
        return mFilter;
    }

    private class HolderView extends FrameLayout {
        private ImageView ivIcon;
        private TextView tvTitle;

        public HolderView(Context context, AttributeSet attrs) {
            super(context, attrs);
            View v = LayoutInflater.from(context).inflate(R.layout.common_pop_item, this);
            tvTitle = (TextView) v.findViewById(R.id.tvTitle);
        }

        public void bindData(String title) {
            tvTitle.setText(title);
        }
    }

    private class ItemFilter extends Filter {//过滤匹配结果
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            String filterString = constraint.toString().toLowerCase();

            FilterResults results = new FilterResults();

            final List<CommonItemModel> list = sunItems;

            int count = list.size();
            final List<CommonItemModel> nlist = new ArrayList<CommonItemModel>(count);

            String filterableString ;

            for (int i = 0; i < count; i++) {
                filterableString = list.get(i).text;
                if (filterableString.toLowerCase().contains(filterString)) {
                    nlist.add(list.get(i));
                }
            }

            results.values = nlist;
            results.count = nlist.size();

            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            filteredData = (List<CommonItemModel>) results.values;
            notifyDataSetChanged();
        }
    }

    public static class CommonItemModel{
        public String text;
        public String workShopId;//车间id
        public String productId;
        public String typeDetail;
    }

}

2, EditText监听

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

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            mSearchContentLv.setVisibility(View.VISIBLE);
            mSearchableAdapter.getFilter().filter(s.toString());
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
HolderView item view 处理

@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
    HolderView holderView;
    // Important to not just null check, but rather to a instanceof
    // since we might get any subclass of view here.
    if (convertView instanceof HolderView) {
        holderView = (HolderView) convertView;
    } else {
        holderView = new HolderView(mContext);
    }
    holderView.bind(new Digit(i));

    return holderView;
}

class HolderView extends FrameLayout{
        //private Context ctx;
        private View vroot;

        public HolderView(Context context) {
            super(context);
            init(context);
        }

        public HolderView(Context context, AttributeSet attrs, View vroot) {
            super(context, attrs);
            init(context);
        }

        private void init(Context context){
            vroot = LayoutInflater.from(context).inflate(R.layout.flyrecoder_item, this);
            ButterKnife.bind(this, vroot);
        }

		void bindData(FlyRecordData model){
					this.tv_fly_record_item_title.setText(model.itemTitle);
					this.tv_fly_record_title_today.setText(model.todayData);
		}			
 }


在展示窗体内容时添加对view统一处理

mLayoutInflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        mViewGroup = (ViewGroup) activity
                .findViewById(android.R.id.content);

        mToastView = mLayoutInflater.inflate(R.layout.supertoast,
                mViewGroup, false);

        mMessageTextView = (TextView) mToastView
                .findViewById(R.id.message_textview);


指定content view中头部或底部加入其它的view

private void setPoppyViewOnView(View view) {
		LayoutParams lp = view.getLayoutParams();
		ViewParent parent = view.getParent();
		ViewGroup group = (ViewGroup)parent;
		int index = group.indexOfChild(view);
		final FrameLayout newContainer = new FrameLayout(mActivity);
		group.removeView(view);
		group.addView(newContainer, index, lp);
		newContainer.addView(view);
		final FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		layoutParams.gravity = mPoppyViewPosition == PoppyViewPosition.BOTTOM ? Gravity.BOTTOM : Gravity.TOP;
		newContainer.addView(mPoppyView, layoutParams);
		group.invalidate();
	}

public enum PoppyViewPosition {
		TOP, BOTTOM
	};
private View mPoppyView;

强制measure childview 方法:

 private void measureView(View child) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }

        int childWidthSpec = ViewGroup.getChildMeasureSpec(0,
                0 + 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }

设置图片叠加层(参差不齐效果)

Drawable[] array = new Drawable[2];       
array[0] = getResources().getDrawable(R.drawable.qq_girl);       
array[1] = getResources().getDrawable(R.drawable.qq_boy);       
LayerDrawable la = new LayerDrawable(array);       
// 其中第一个参数为层的索引号,后面的四个参数分别为left、top、right和bottom       
la.setLayerInset(0, 0, 0, 0, 0);       
la.setLayerInset(1, 18, 35, 180, 76);       
image.setImageDrawable(la);  

也可在xml实现
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/compassbackground" />
    <item android:drawable="@drawable/compass_text" />
</layer-list>

 
扩大控件有效点击区域(以imageview为例,当图片较小时,点击会有不灵敏感觉)这里需要设置scaleType属性

改进:
<ImageView
      android:layout_width="100dp"
      android:layout_height="100dp"
       android:src="@drawable/edit"
      android:scaleType="centerInside"/>
这里设置路ImageView的大小,这个大小区域就是ImageViwe的有效的点击区域,可以根据自己的情况修改大小
需要注意的是: 要使用 src 不能使用background 否则图像会被拉伸

使用TouchDelegate扩展区域:

public static void setTouchDelegate(final View view, final int expandTouchWidth) {
        final View parentView = (View) view.getParent();
        parentView.post(new Runnable() {
            @Override
            public void run() {
                final Rect rect = new Rect();
                view.getHitRect(rect); // view构建完成后才能获取,所以放在post中执行
                
                rect.top -= expandTouchWidth;
                rect.bottom += expandTouchWidth;
                rect.left -= expandTouchWidth;
                rect.right += expandTouchWidth;

                parentView.setTouchDelegate(new TouchDelegate(rect, view));
            }
        });
    }

在touch屏幕上某点时,判断点击是否在某个widget控件内:

Rect mTouchRect = new Rect();
 private boolean isTouchedView(View view, float x, float y) {
        view.getHitRect(mTouchRect);

        // by taping top or bottom padding, the list performs on click on a border item.
        // we don't add top padding here to keep behavior consistent.
      //  mTouchRect.top += mTranslateY;

      //  mTouchRect.bottom += mTranslateY + getPaddingTop();
      //  mTouchRect.left += getPaddingLeft();
      //  mTouchRect.right -= getPaddingRight();
        return mTouchRect.contains((int)x, (int)y);
    }

 
activity设置背景透明 getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));   

view背景透明设置
android:background
以下两种方法设置背景为透明:"@android :color/transparent"和"@null"

GirdView,ListView设置divide透明    gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));


隐去标题栏,  隐去状态栏 android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
设置透明背景,修改AndroidManifest.xml文件,在对应的Activity里面加上下面的属性:
android:theme="@android:style/Theme.Translucent"
使用系统背景作为应用的背景,在onCreate的时候添加窗口标志:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
android:theme="@android:style/Theme.Dialog"


dialog级别设置 ctx不依赖Activity
 AlertDialog mDialog=dialog.create();  
 mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);//设定为系统级警告,关键   

<activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >
 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间

//强制为横屏   
 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
<activity android:name=".HandlerActivity" android:screenOrientation="landscape"/>  

//强制为竖屏   
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
<activity android:name=".HandlerActivity" android:screenOrientation="portrait"/>

AndroidManifest.xml 中设置属性禁止重新创建Activity,并且添加屏幕切换监听。
<activity android:name=".HandlerActivity"
sdk<3.2 android:configChanges="orientation|keyboardHidden"/>
dk>3.2 android:configChanges="orientation|screenSize"



handler清理所有消息内容   mHandler.removeCallbacksAndMessages(null); 

//获取View在窗口/屏幕中的位置
TextView tv= (TextView) findViewById(R.id.tv);
int loc[]=new int[2];
tv.getLocationInWindow(loc);
Log.e("TAG",loc[0]+" "+loc[1]);


根据widget资源名称获取对应ID:   
int resID = getResources().getIdentifier("widget_id", "id",  getPackageName());
View addButton = findViewById(resID);

View中的isShown()方法,以前都是用view.getVisibility() == View.VISIBLE来判断的,但是与这个函数还是有区别的。
 也就是只有当view本身和它的所有父容器都是visible时,isShown()才返回TRUE。
 而平常我们调用if(view.getVisibility() == View.VISIBLE)只是对view本身而不对父容器的可见性进行判断。


直接获取view,不需要强制转型

public static <T> T $(View vroot,int viewID) {
        return (T) vroot.findViewById(viewID);
    }

使用:
Button takePicture = Utils.$(v, R.id.start_camera);

颜色值创建Drawable对象

private Drawable createDrawable(int color) {
        OvalShape ovalShape = new OvalShape();
        ShapeDrawable shapeDrawable = new ShapeDrawable(ovalShape);
        shapeDrawable.getPaint().setColor(color);
 
        if (mShadow && !hasLollipopApi()) {
            Drawable shadowDrawable = getResources().getDrawable(mType == TYPE_NORMAL ? R.drawable.fab_shadow
                    : R.drawable.fab_shadow_mini);
            LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shadowDrawable, shapeDrawable});
            layerDrawable.setLayerInset(1, mShadowSize, mShadowSize, mShadowSize, mShadowSize);
            return layerDrawable;
        } else {
            return shapeDrawable;
        }
    }

 代码实现按钮按压效果颜色变化:

private void updateBackground() {
        StateListDrawable drawable = new StateListDrawable();
        drawable.addState(new int[]{android.R.attr.state_pressed}, createDrawable(mColorPressed));
        drawable.addState(new int[]{-android.R.attr.state_enabled}, createDrawable(mColorDisabled));
        drawable.addState(new int[]{}, createDrawable(mColorNormal));
        setBackground(drawable);
    }

 悬浮属性设置:

UC浏览器中文版出了一个快速搜索的功能,
显示这个悬浮窗不需要申请android.permission.SYSTEM_ALERT_WINDOW权限
一般设置成TYPE_PHONE就可以悬浮在很多view的上方了, 但是调用这个方法需要申请android.permission.SYSTEM_ALERT_WINDOW权限,
将type设置成TYPE_TOAST果然有奇效, 但是在2.3上不能接收点击事件.
TYPE_APPLICATION_PANEL: 只能配合Activity在当前APP使用(PopupWindow默认就是这个Type)
TYPE_CHANGED: 只能配合Activity在当前APP使用


绘制扇形进度加载

public void draw(Canvas canvas) {
        if (getHideWhenZero() && mLevel == 0) {
            return;
        }
        drawBar(canvas, maxLevel, getBackgroundColor());
        drawBar(canvas, mLevel, getColor());
    }
    
    private void drawBar(Canvas canvas, int level, int color) {
        Rect bounds = getBounds();
        RectF rectF = new RectF((float) (bounds.right * .4), (float) (bounds.bottom * .4),
                (float) (bounds.right * .6), (float) (bounds.bottom * .6));
        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(6);
        if (level != 0)
            canvas.drawArc(rectF, 0, (float) (level * 360 / maxLevel), false, mPaint);
    }


屏幕截取

/**
     * 获取当前屏幕截图,包含状态栏
     */
    public static Bitmap snapShotWithStatusBar(Activity activity){
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
        view.destroyDrawingCache();
        return bp;
    }
 
    /**
     * 获取当前屏幕截图,不包含状态栏
     *
     */
    public static Bitmap snapShotWithoutStatusBar(Activity activity){
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;
        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
                - statusBarHeight);
        view.destroyDrawingCache();
        return bp;
    }

Bitmap大小计算

static int getBitmapBytes(Bitmap bitmap) {
    int result;
    if (SDK_INT >= HONEYCOMB_MR1) {
      result = BitmapHoneycombMR1.getByteCount(bitmap);
    } else {
      result = bitmap.getRowBytes() * bitmap.getHeight();
    }
    if (result < 0) {
      throw new IllegalStateException("Negative size: " + bitmap);
    }
    return result;
  }


保存恢复ListView当前位置

private void saveCurrentPosition() {
        if (mListView != null) {
            int position = mListView.getFirstVisiblePosition();
            View v = mListView.getChildAt(0);
            int top = (v == null) ? 0 : v.getTop();
            //保存position和top
        }
    }
    
    private void restorePosition() {
        if (mFolder != null && mListView != null) {
            int position = 0;//取出保存的数据
            int top = 0;//取出保存的数据
            mListView.setSelectionFromTop(position, top);
        }
    }


帮助、about、关于作者、HELP等的提示dialog页面

	//方法一:
 AlertDialog ad = new AlertDialog.Builder(SettingPreference.this)
	                        .setTitle(R.string.about_dlg_title)
	                        .setMessage(R.string.about_dlg_message)
	                        .setPositiveButton(getText(R.string.ok), null).create();
	                ad.show();
					//加入链接功能
	                Linkify.addLinks((TextView) ad.findViewById(android.R.id.message),
	                        Linkify.ALL);

//方法二:
//设计一个AboutDialog类继承于AlertDialog
public class AboutDialog extends AlertDialog {   
    public AboutDialog(Context context) {   
        super(context);   
        final View view = getLayoutInflater().inflate(R.layout.about,   
                null);   
        setButton(context.getText(R.string.close), (OnClickListener) null);   
        setIcon(R.drawable.icon_about);   
        setTitle("程序版本   v1.0.0" );   
        setView(view);   
    }   

布局文件about.xml

<?xml version="1.0" encoding="utf-8"?>  
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" android:layout_height="wrap_content">  
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
        android:layout_width="fill_parent" android:layout_height="fill_parent">  
   
        <TextView android:layout_height="fill_parent" 
            android:layout_width="fill_parent" android:text="@string/help_dialog_text" 
            android:padding="6dip" android:textColor="#FFFFFF" />  
    </ScrollView>  
</FrameLayout>  



自定义View相关问题:

measure解析:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
		int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
		setMeasuredDimension(width, height);
	}


protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int count = getChildCount();

		int maxHeight = 0;
		int maxWidth = 0;

		measureChildren(widthMeasureSpec, heightMeasureSpec);

		for (int i = 0; i < count; i++) {
			View child = getChildAt(i);
			if (child.getVisibility() != GONE) {
				int childRight;
				int childBottom;

				CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams();

				childRight = lp.x + child.getMeasuredWidth();
				childBottom = lp.y + child.getMeasuredHeight();

				maxWidth = Math.max(maxWidth, childRight);
				maxHeight = Math.max(maxHeight, childBottom);
			}
		}

		maxWidth += mPaddingLeft + mPaddingRight;
		maxHeight += mPaddingTop + mPaddingBottom;

		maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
		maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

		setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec));
	}
@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //DensityUtils.dp2px(getContext(),40)+
        int minWidth = getPaddingLeft() + getPaddingRight();
        int minHeight = barHeight + getPaddingBottom() + getPaddingTop();

        int w = resolveSizeAndState(minWidth, widthMeasureSpec, 0);
        int h = resolveSizeAndState(minHeight, heightMeasureSpec, 0);

        setMeasuredDimension(w, h);
    }

绘制文本居中显示:

 public void drawTextCentredInRectWithSides(Canvas canvas, Paint paint, String text, float left, float top, float right, float bottom) {
        paint.setTextAlign(Paint.Align.CENTER);

        float textHeight = paint.descent() - paint.ascent();
        float textOffset = (textHeight / 2) - paint.descent();

        canvas.drawText(text, (left + right) / 2, (top + bottom) / 2 + textOffset, paint);
    }

绘制局部圆角

1,绘制完整圆角 canvas.drawRoundRect

2,去除部分圆角,在要去除地方,在绘制一次小的矩形使其变为方角

    private void clipTopLeft(final Canvas canvas, final Paint paint, int offset,int left,int top) {
        Rect block = new Rect(left, top, left+offset, top+offset);
        canvas.drawRect(block, paint);
    }

    private void clipTopRight(final Canvas canvas, final Paint paint, int offset, int right,int top) {
        Rect block = new Rect(right - offset, top, right, top+offset);
        canvas.drawRect(block, paint);
    }

    private void clipBottomLeft(final Canvas canvas, final Paint paint, int offset, int left, int bottom) {
        Rect block = new Rect(left, bottom - offset, left+offset, bottom);
        canvas.drawRect(block, paint);
    }

    private void clipBottomRight(final Canvas canvas, final Paint paint, int offset, int right, int bottom) {
        Rect block = new Rect(right - offset, bottom - offset, right, bottom);
        canvas.drawRect(block, paint);
    }

 带进度webview

public class ProgressWebView extends WebView {
 
    private ProgressBar progressbar;
 
    public ProgressWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        progressbar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal);
        progressbar.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, 3, 0, 0));
        addView(progressbar);
        //        setWebViewClient(new WebViewClient(){});
        setWebChromeClient(new WebChromeClient());
    }
 
    public class WebChromeClient extends android.webkit.WebChromeClient {
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            if (newProgress == 100) {
                progressbar.setVisibility(GONE);
            } else {
                if (progressbar.getVisibility() == GONE)
                    progressbar.setVisibility(VISIBLE);
                progressbar.setProgress(newProgress);
            }
            super.onProgressChanged(view, newProgress);
        }
 
    }
 
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        LayoutParams lp = (LayoutParams) progressbar.getLayoutParams();
        lp.x = l;
        lp.y = t;
        progressbar.setLayoutParams(lp);
        super.onScrollChanged(l, t, oldl, oldt);
    }
}

 textview文字图片一起水平居中

public class DrawableCenterTextView extends TextView {
......
    @Override
    protected void onDraw(Canvas canvas) {
        Drawable[] drawables = getCompoundDrawables();
        if (drawables != null) {
            Drawable drawableLeft = drawables[0];
            if (drawableLeft != null) {//左边图片处理
                float textWidth = getPaint().measureText(getText().toString());
                int drawablePadding = getCompoundDrawablePadding();
                int drawableWidth = 0;
                drawableWidth = drawableLeft.getIntrinsicWidth();
                float bodyWidth = textWidth + drawableWidth + drawablePadding;
                canvas.translate((getWidth() - bodyWidth) / 2, 0);
            }
        }
         
        Drawable drawableRight = drawables[2];
        if (drawableRight != null) {//右边图像处理
            float textWidth = getPaint().measureText(getText().toString());
            int drawablePadding = getCompoundDrawablePadding();
            int drawableWidth = 0;
            drawableWidth = drawableLeft.getIntrinsicWidth();
            float bodyWidth = textWidth + drawableWidth + drawablePadding;
            setPadding(0, 0, (int)(getWidth() - bodyWidth), 0);
            canvas.translate((getWidth() - bodyWidth) / 2, 0);
        }
        super.onDraw(canvas);
    }
     
}

底部导航tab中间button高出一部分内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:orientation="vertical" >
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="48dip"
        android:background="#B0C4DE"
        android:orientation="horizontal" >
 
        <ImageView
            android:layout_width="0dip"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"
            android:scaleType="fitCenter"
            android:src="@drawable/ic_launcher" />
             
         <ImageView
             android:layout_width="0dip"
            android:layout_height="64dip"
            android:layout_gravity="bottom"
            android:layout_weight="1.0"
            android:scaleType="fitCenter"
            android:src="@drawable/ic_launcher" />
    </LinearLayout>  
     
</LinearLayout>   

 1、只需在根节点设置android:clipChildren为false即可,默认为true
 2、可以通过android:layout_gravity控制超出的部分如何显示。
 3、android:clipChildren的意思:是否限制子View在其范围内



原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6818930.html