一.按照宽高比例显示图片
1.
/**设置专题的图片大小比例,都是一样的比例宽高*/
public class RationLayout extends FrameLayout{
public RationLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TypedArray typearray = context.obtainStyledAttributes(attrs, R.styleable.Ratiolayout);
// float ratio = typearray.getFloat(R.styleable.Ratiolayout_ratio, 0f);
// typearray.recycle();//保持一致
float ratio = attrs.getAttributeFloatValue("http://schemas.android.com/apk/res/com.example.play", "ratio", 0f);
setRatio(ratio);
}
private void setRatio(float ratio) {
this.rotio = ratio ;
}
public RationLayout(Context context) {
super(context);
}
float rotio;//比例
private int width;
private int height;
//父容器(ViewGroup的测量规则)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
width = widthSize - getPaddingLeft() - getPaddingRight();
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heighSize = MeasureSpec.getSize(heightMeasureSpec);
height = heighSize - getPaddingTop() - getPaddingBottom();
//如果宽是精确的高不是,就按照宽来制定高
if(widthMode==MeasureSpec.EXACTLY&&heightMode!=MeasureSpec.EXACTLY){
height = (int) (width / rotio + 0.5f);
//如果高是精确的宽不是,就按照高来制定宽
}else if(widthMode!=MeasureSpec.EXACTLY&&heightMode==MeasureSpec.EXACTLY){
width = (int) (height * rotio + 0.5f);
}
//重新制定一个测量规则
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.EXACTLY,width + getPaddingLeft() +getPaddingRight());
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
MeasureSpec.EXACTLY,height + getPaddingTop() +getPaddingBottom());
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
xml文件
<com.example.play.view.RationLayout
android:id="@+id/fl_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
gan:ratio="2.43"
android:padding="5dp" >
<ImageView
android:id="@+id/item_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/ic_default" />
</com.example.play.view.RationLayout>
2.自定义属性,设置比例
①.设置attrs下的xml
<resources>
<declare-styleable name="Ratiolayout">//设置集合名字
<attr name="ratio" format="float" />//设置特定的属性名字
</declare-styleable>
</resources>
②.获取属性
public RationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
<span style="white-space:pre"> </span>//第一种方式,这种最佳,可以解析 id的国际化设置
// TypedArray typearray = context.obtainStyledAttributes(attrs, R.styleable.Ratiolayout);//根据集合名字获取集合
// float ratio = typearray.getFloat(R.styleable.Ratiolayout_ratio, 0f);//根据特定名字获取该属性
// typearray.recycle();//保持一致
<span style="white-space:pre"> </span>//第2中方式.通过xml中的命名空间 和 属性名字 获取属性
float ratio = attrs.getAttributeFloatValue("http://schemas.android.com/apk/res/com.example.play", "ratio", 0f);
setRatio(ratio);
}
3.xml中设置ratio属性的值
xmlns:gan="http://schemas.android.com/apk/res/com.example.play"
<com.example.play.view.RationLayout
android:id="@+id/fl_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
gan:ratio="2.43"
android:padding="5dp" ><!-- 设置自定义属性 -->
二.代码设置排行页面的布局
1.自定义线性布局添加textView ,设置textVIew的选择器
@Override
protected View createSuccessView() {
ScrollView scrollView = new ScrollView(BaseApplication.getApplication());
//LinearLayout linearLayout = new LinearLayout(BaseApplication.getApplication());
FlowLayout linearLayout = new FlowLayout(BaseApplication.getApplication());
int padding = Uiutils.dip2px(13);
linearLayout.setPadding(padding, padding, padding, padding);
//linearLayout.setOrientation(LinearLayout.VERTICAL);//设置线性排列
//-----------------------因为需要根据网络读取有多少字段,所以代码设置TextView
for (int i = 0; i < data.size(); i++) {
final String des = data.get(i);
//文字设置
TextView textView = new TextView(BaseApplication.getApplication());
textView.setText(data.get(i));
textView.setTextColor(Color.WHITE);
//随机颜色
Random random = new Random();
int red = random.nextInt(200)+20;
int green = random.nextInt(200)+20;
int blue = random.nextInt(200)+20;
int color = Color.rgb(red, green, blue);
//设置选择器
int backColor = 0xffcecece;
GradientDrawable pressDrawable = GradientUtils.getGradientDrawable(backColor);//按下的图片
GradientDrawable defaultDrawable = GradientUtils.getGradientDrawable(color);//默认的图片
//状态选择器
textView.setBackgroundDrawable(GradientUtils.getStateListDrawable(pressDrawable, defaultDrawable));
//设置边距
int PaddingL = Uiutils.dip2px(4);
int PaddingH = Uiutils.dip2px(7);
textView.setPadding(PaddingH, PaddingL, PaddingH, PaddingL);//给textView设置padding距离父亲
textView.setClickable(true);
textView.setGravity(Gravity.CENTER);
//点击事件
textView.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(BaseApplication.getApplication(), des, 0).show();
}
});
//设置textView包裹内容
linearLayout.addView(textView,new LayoutParams(LayoutParams.WRAP_CONTENT, -2));
}
scrollView.addView(linearLayout);
return scrollView;
}
2.设置布局,一个线性布局根据textView的大小填充
public class FlowLayout extends ViewGroup {
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FlowLayout(Context context) {
super(context);
init();
}
private void init() {
}
// Viewgroup必须实现的方法。因为要对孩子分配位置
// 怎么分配位置?----1.对孩子进行测量
// ----2.然后才进行分配位置
//
/** 1.对孩子进行测量 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
lines.clear();
currentLine = null;
// ------------父亲FlowLayout的大小和模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();// 宽
height = MeasureSpec.getSize(heightMeasureSpec)-getPaddingTop()-getPaddingBottom();// 高
// ------------根据父亲的模式获得孩子的测量规则
int childWidthMode;
int childHeightMode;
// 模式
childWidthMode = (widthMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST
: widthMode);
childHeightMode = (heightMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST
: heightMode);
// 测量规则
int childwidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthMode,width);
int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightMode, height);
// 测量
currentLine = new Line();// 创建一个新行
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
getChildAt(i)
.measure(childwidthMeasureSpec, childheightMeasureSpec);
int textViewWidth = child.getMeasuredWidth();// 获得textView的高度
useWidth = useWidth + textViewWidth;// 加到使用的里面去
if (useWidth > width) {
if (currentLine.getChildCount() < 1) {
currentLine.addLine(child);
}
newLine();// 如果使用的行的宽度>行宽,换行
} else { // 否则添加TextView到这个行里面
currentLine.addLine(child);
useWidth = useWidth + horizontalSpace;// 加上间隔
if (useWidth > width) {
newLine();// 如果加了间隔大于行宽,换行
}
}
}
if (!lines.contains(currentLine)) {// 添加最后一行
lines.add(currentLine);
}
// 行的总高度
int totalheight = 0;
for (Line line : lines) {
totalheight += line.getheight();// 获取所有行的高
}
totalheight += (lines.size() - 1) * verticalSpace+getPaddingBottom()+getPaddingTop();// 加上行的间隔
// 按照自己的宽高去设置
setMeasuredDimension(width+getPaddingLeft()+getPaddingRight(), resolveSize(totalheight, heightMeasureSpec));
}
/** 2.分配位置 */
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
l = l +getPaddingLeft();
t= t +getPaddingTop();
for (int i = 0; i < lines.size(); i++) {// 分配每行
Line line = lines.get(i);
line.layout(l, t);// 让孩子自己去做
t += line.getheight() + verticalSpace;// 行高 + 间隔
}
}
private List<Line> lines = new ArrayList<Line>();// 所有行的集合
private Line currentLine;// 当前行
private int useWidth = 0;// 使用的行的宽度
private int horizontalSpace = Uiutils.dip2px(13);
private int verticalSpace = Uiutils.dip2px(13);
private int width;
private int height;
class Line {
private List<View> children = new ArrayList<View>();
private int height;// 行高就等于孩子的高
int lineWidth;// 孩子的宽的和
private int surplusWidth = 0;// 一行剩余的宽度
// 添加一个孩子
public void addLine(View child) {
if (child.getMeasuredHeight() > height) {// 如果下一个高度大于上一个的高度,就按照大的来
height = child.getMeasuredHeight();
}
children.add(child);
lineWidth += child.getMeasuredWidth();
}
// 该行的TextView的个数
public int getChildCount() {
return children.size();
}
// 分配孩子的位置
public void layout(int l, int t) {
int aveWidth = 0;
lineWidth += horizontalSpace * (children.size() - 1);// 加上间隔的和
surplusWidth = width - lineWidth;// 剩余的空间
if (surplusWidth > 0) {
if (children.size() > 0) {
aveWidth = surplusWidth / (children.size());
}
}
for (int i = 0; i < children.size(); i++) {
View child = children.get(i);
// 分配每个孩子的位置
child.layout(l, t, l + child.getMeasuredWidth()+ aveWidth,
t + child.getMeasuredHeight());
l += child.getMeasuredWidth()+ aveWidth;
l += horizontalSpace ;
// t += child.getMeasuredHeight()*i;
}
}
// 获得行的高度
public int getheight() {
return height;
}
}
/** 换行 */
private void newLine() {
lines.add(currentLine);
currentLine = new Line();// 重新建立一个当前行对象
useWidth = 0;// 使用的行的宽设为0;
}
}