15.瀑布流、测量

排行界面

TopProtocol :json数据就是写字符串,所以不需要写bean对象

public class TopProtocol extends BaseProtocol<List<String>> {
 @Override
 public List<String> paserJson(String json) {
 List<String> datas=new ArrayList<String>();
 try {
 JSONArray array=new JSONArray(json);
 for(int i=0;i<array.length();i++){
 String str=array.getString(i);
				datas.add(str);
 }
 return datas;
 } catch (JSONException e) {
			e.printStackTrace();
 return null;
 }
 }
 @Override
 public String getKey() {
 return "hot";
 }
}

DrawableUtils :用代码创建状态选择器 和圆角

public class DrawableUtils {
 public static GradientDrawable createShape(int color){
 GradientDrawable drawable=new GradientDrawable();//相当于shape
		drawable.setCornerRadius(UiUtils.dip2px(5));//设置4个角的弧度 
		drawable.setColor(color);// 设置颜色
 return drawable;
 }
 public static StateListDrawable createSelectorDrawable(Drawable pressedDrawable,Drawable normalDrawable){
//		<selector xmlns:android="http://schemas.android.com/apk/res/android"  android:enterFadeDuration="200">
//	    <item  android:state_pressed="true" android:drawable="@drawable/detail_btn_pressed"></item>
//	    <item  android:drawable="@drawable/detail_btn_normal"></item>
//	</selector>
 StateListDrawable stateListDrawable=new StateListDrawable();
		stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);// 按下显示的图片
		stateListDrawable.addState(new int[]{}, normalDrawable);// 抬起显示的图片
 return stateListDrawable;
 }

TopFragment :使用代码创建、随机色

MATCH_PARENT 、FILL_PARENT是-1且他俩个没有任何区别,WRAP_CONTENT是-2

public class TopFragment extends BaseFragment {
 private List<String> datas;
 @Override
 public View createSuccessView() {
 ScrollView scrollView=new ScrollView(UiUtils.getContext());
		scrollView.setBackgroundResource(R.drawable.grid_item_bg_normal);
 LinearLayout layout=new LinearLayout(UiUtils.getContext());
 int padding=UiUtils.dip2px(13);
		layout.setPadding(padding, padding, padding, padding);
 layout.setOrientation(LinearLayout.VERTICAL);// 设置线性布局的方向
 int backColor = 0xffcecece;
 Drawable pressedDrawable=DrawableUtils.createShape(backColor);// 按下显示的图片
 for(int i=0;i<datas.size();i++){
 TextView textView=new TextView(UiUtils.getContext());
 final String str=datas.get(i);
			textView.setText(str);
 Random random=new Random(); //创建随机
 int red = random.nextInt(200)+22; 
 int green = random.nextInt(200)+22; 
 int blue = random.nextInt(200)+22;//有可能都是0或255成白色或者黑色了 
 int color=Color.rgb(red, green, blue);//范围 0-255 
 GradientDrawable createShape = DrawableUtils.createShape(color); // 默认显示的图片
 StateListDrawable createSelectorDrawable = DrawableUtils.createSelectorDrawable(pressedDrawable, createShape);// 创建状态选择器
			textView.setBackgroundDrawable(createSelectorDrawable);
			textView.setTextColor(Color.WHITE);
 //textView.setTextSize(UiUtils.dip2px(14));
 int textPaddingV = UiUtils.dip2px(4);
 int textPaddingH = UiUtils.dip2px(7);
			textView.setPadding(textPaddingH, textPaddingV, textPaddingH, textPaddingV); //设置padding 
			textView.setClickable(true);//设置textView可以被点击
			textView.setOnClickListener(new OnClickListener() { // 设置点击事件
 @Override
 public void onClick(View v) {
 Toast.makeText(UiUtils.getContext(), str, 0).show();
 }
 });
			layout.addView(textView,new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, -2));// -2 包裹内容
 }
		scrollView.addView(layout);
 return scrollView;
 }
 @Override
 protected LoadResult load() {
 TopProtocol protocol=new TopProtocol();
		datas = protocol.load(0);
 return checkData(datas);
 }
}

到目前为止实现的效果是这样的,将LinearLayout使用一个自定义控件


Flowlayout

原理

public class Flowlayout extends ViewGroup {
 private int horizontolSpacing=UiUtils.dip2px(13);
 private int verticalSpacing=UiUtils.dip2px(13);
 public Flowlayout(Context context) {
 super(context);
 }
 public Flowlayout(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 }
 private Line currentline;// 当前的行 
 private int useWidth=0;// 当前行使用的宽度
 private List<Line> mLines=new ArrayList<Flowlayout.Line>();
 private int width;
 public Flowlayout(Context context, AttributeSet attrs) {
 super(context, attrs);
 }
 // 测量 当前控件Flowlayout 
 // 父类是有义务测量每个孩子的 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 // TODO Auto-generated method stub
//		MeasureSpec.EXACTLY;
//		MeasureSpec.AT_MOST;
//		MeasureSpec.UNSPECIFIED;
		mLines.clear();
		currentline=null;
		useWidth=0;
 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 int heightMode = MeasureSpec.getMode(heightMeasureSpec); //  获取当前父容器(Flowlayout)的模式
		width = MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();
 int height = MeasureSpec.getSize(heightMeasureSpec)-getPaddingBottom()-getPaddingTop(); // 获取到宽和高 
 int childeWidthMode;
 int childeHeightMode;
 //  为了测量每个孩子 需要指定每个孩子测量规则 	
		childeWidthMode=(widthMode==MeasureSpec.EXACTLY)?MeasureSpec.AT_MOST:widthMode;
		childeHeightMode=heightMode==MeasureSpec.EXACTLY?MeasureSpec.AT_MOST:heightMode;
 int childWidthMeasureSpec=MeasureSpec.makeMeasureSpec(childeWidthMode,  width);
 int childHeightMeasureSpec=MeasureSpec.makeMeasureSpec(childeHeightMode,  height);
		currentline=new Line();// 创建了第一行 
 for(int i=0;i<getChildCount();i++) {
 View child=getChildAt(i);
 System.out.println("孩子的数量:"+getChildCount());
 // 测量每个孩子
			child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
 int measuredWidth = child.getMeasuredWidth();
			useWidth+=measuredWidth;// 让当前行加上使用的长度 
 if(useWidth<=width){
				currentline.addChild(child);//这时候证明当前的孩子是可以放进当前的行里,放进去
				useWidth+=horizontolSpacing;
 if(useWidth>width){
 //换行 
					newLine();
 }
 }else{
 //换行   
 if(currentline.getChildCount()<1){
					currentline.addChild(child); // 保证当前行里面最少有一个孩子 
 }
				newLine();
 }
 }
 if(!mLines.contains(currentline)){
			mLines.add(currentline);// 添加最后一行
 }
 int  totalheight=0;
 for(Line line:mLines){
			totalheight+=line.getHeight();
 }
		totalheight+=verticalSpacing*(mLines.size()-1)+getPaddingTop()+getPaddingBottom();
 System.out.println(totalheight);
		 setMeasuredDimension(width+getPaddingLeft()+getPaddingRight(),resolveSize(totalheight, heightMeasureSpec));
 }
 private void newLine() {
		mLines.add(currentline);// 记录之前的行
		currentline=new Line(); // 创建新的一行
		useWidth=0;
 }
 private class Line{
 int height=0; //当前行的高度
 int lineWidth=0;
 private List<View> children=new ArrayList<View>();
 /**
		 * 添加一个孩子
		 * @param child
		 */
 public void addChild(View child) {
			children.add(child);
 if(child.getMeasuredHeight()>height){
				height=child.getMeasuredHeight();
 }
			lineWidth+=child.getMeasuredWidth();
 }
 public int getHeight() {
 return height;
 }
 /**
		 * 返回孩子的数量
		 * @return
		 */
 public int getChildCount() {
 return children.size();
 }
 public void layout(int l, int t) {
			lineWidth+=horizontolSpacing*(children.size()-1);
 int surplusChild=0;
 int surplus=width-lineWidth;
 if(surplus>0){
				surplusChild=surplus/children.size();
 }
 for(int i=0;i<children.size();i++){
 View child=children.get(i);
 //  getMeasuredWidth()   控件实际的大小
 // getWidth()  控件显示的大小
				child.layout(l, t, l+child.getMeasuredWidth()+surplusChild, t+child.getMeasuredHeight());
				l+=child.getMeasuredWidth()+surplusChild;
				l+=horizontolSpacing;
 }
 }
 }
 // 分配每个孩子的位置 
 @Override
 protected void onLayout(boolean changed, int l, int t, int r, int b) {
		l+=getPaddingLeft();
		t+=getPaddingTop();
 for(int i=0;i<mLines.size();i++){ 
 Line line=mLines.get(i);
			line.layout(l,t); //交给每一行去分配
			t+=line.getHeight()+verticalSpacing;
 }
 }
}

如果不要平均分配那些步骤,实现的效果是这样的


自定义一个圆形的进度条

public class ProgressView extends View {
 public ProgressView(Context context) {
 super(context);
 }
 public ProgressView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 }
 public ProgressView(Context context, AttributeSet attrs) {
 super(context, attrs);
 }
 // 绘制控件
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 //canvas.drawBitmap(bitmap, left, top, paint);
 /*oval  圆的模型 矩形
		 * startAngle 开始的角度
		 * sweepAngle  范围的角度
		 * useCenter  是否填充中间部分
		 * paint   画笔
		 */
 //canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
 }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏移动开发

ZoomLoadView 自定义view 可以做app的启动首页效果

虽然这个控件类似的功能github上也有,但还是自己实现了下. 这个控件可以保持图片的比例去填充view,如果按图片比例计算出的大小超出view的大小,会展...

911
来自专栏Android知识点总结

Android自定义控件之局部图片放大镜--BiggerView

2042
来自专栏Android知识点总结

Android关于Paint你所知道的和不知道的一切

2412
来自专栏肖蕾的博客

Android自定义控件之九宫格

2195
来自专栏向治洪

AnimatedPathView实现自定义图片标签

老早用过小红书app,对于他们客户端笔记这块的设计非常喜欢,恰好去年在小红书的竞争对手公司,公司基于产品的考虑和产品的发展,也需要将app社交化,于是在社区分享...

21310
来自专栏Hellovass 的博客

手动测量 View 的宽高

手动调用 View 的 measure(int widthMeasureSpec,int heightMeasureSpec) 方法来得到 View 的宽高。

2136
来自专栏Sorrower的专栏

界面无小事(五):自定义TextView

1083
来自专栏肖蕾的博客

Android自定义控件之圆形进度条Android自定义控件之-圆形进度条

1.2K5
来自专栏向治洪

自定义圆角和园边的实现

本来想在网上找个圆角的例子看一看,不尽人意啊,基本都是官方的Demo的那张原理图,稍后会贴出。于是自己自定义了个View,实现图片的圆角以及圆形效果。效果图: ...

2117
来自专栏Android干货

自定义控件:数独游戏(一)

4018

扫码关注云+社区

领取腾讯云代金券