项目里面需要这样一个功能,动态去绘制界面,动态加载界面,View的类型很有几种,都是需要动态加载的那一种 ,网上都是零零碎碎的使用LayoutParams去修改属性,这里做一个封装,给需要的伙伴提供思路和核心代码.
直接以上图为例:
1:底部有一个VideoPlayer控件
2:左上角有一个天气控件(ViewGroup组合控件)
3:右上角是一个ViewPager控件
4:底部还有一个滚动字幕,
遇到这样的复杂的界面,不要着急曾经有个女孩子问我 ,你们程序那么复杂,怎么写的啊 ,我冷静了一下,静静的说,写代码和你们女孩子化妆很相似,要实现一个效果,就要分布实现,集中起来就是最后的效果,先打粉底,隔离霜,腮红,眼线,眉毛,口红...
言归正传,哈哈,扯远了 ,界面我是使用 AbsoluteLayout 来作为基准布局,其他的View都是需要更具坐标点来绘制的,先看主界面布局代码。
然后就是代码布局初始化,这里不贴全部代码,贴一点核心的代码,到时看不懂需要源码的,下面留言,
view_abous = (AbsoluteLayout) findViewById(R.id.view_abous);
playTaskParsener = new PlayTaskParsener(PlayerTaskActivity.this, this);
playTaskParsener.getTaskToView();
因为涉及到界面媒体文件的填充,业务比较多 ,我直接使用MVP来实现界面,这还是测试代码,下面就是填充数据,显示界面的功能.
Generator generatorView;
View view;
public void getTaskToView() {
lists.add("https://goss.vcg.com/creative/vcg/800/new/gic16764018.jpg");
lists.add("https://goss.vcg.com/creative/vcg/800/new/c787d8e71.jpg");
lists.add("https://goss3.vcg.com/creative/vcg/800/new/05135175c.jpg");
lists.add("https://goss3.vcg.com/creative/vcg/800/new/VCG211120950491.jpg");
lists.add("https://goss3.vcg.com/creative/vcg/800/new/gic19964052.jpg");
lists.add("https://goss.vcg.com/creative/vcg/800/new/gic16764018.jpg");
List videoPlayList = new ArrayList<>();
videoPlayList.add("/sdcard/ddd.mp4");
videoPlayList.add("/sdcard/fff.mp4");
videoPlayList.add("/sdcard/zzz.mp4");
videoPlayList.add("/sdcard/ddd.mp4");
videoPlayList.add("/sdcard/fff.mp4");
videoPlayList.add("/sdcard/sss.mp4");
generatorView = new ViewVideoGenertrator(context, 0, 0, 1366, 768, videoPlayList);
view = generatorView.getView();
view_abous.addView(view, generatorView.getLayoutParams());
//==================================================
generatorView = new ViewImageGenertrator(context, 800, 0, 500, 300, lists);
view = generatorView.getView();
view_abous.addView(view, generatorView.getLayoutParams());
//============================================================
//================================================================
WeatherHttpRequest.getWeather(context, new WeatherHttpRequest.WeatherStateListener() {
@Override
public void getWeatherState(WeatherEntity entity) {
ViewWeatherGenerate viewWeatherGenerate = new ViewWeatherGenerate(context, 0, 0, 300, 250);
view = viewWeatherGenerate.getView();
view_abous.addView(view, viewWeatherGenerate.getLayoutParams());
viewWeatherGenerate.updateWeatherView(entity);
}
@Override
public void getFailed(String desc) {
}
});
//=========================================================================================
generatorView = new ViewMatQueentestGenerte(context, 0, 680, 1366, 60, "asdfasfaioewrujhfialsjfdbaiueygrfkasjsdfgsdgdreyjhdrgblajsbfvsvbgfka,xzbcvhkasdfkaushvfasdvczsdvbkusadryhjgfauksfdjvbsayuerijbaysfdv");
view = generatorView.getView();
view_abous.addView(view, generatorView.getLayoutParams());
}
Generator到死是什么鬼 ?来揭开面纱,它定义的布局基本参数,获取View参数,以及界面清理的方法,
看到这里,估计大家基本一目了然了 ,这面就展示两个简单继承View.
package com.etv.view.layout;
import android.content.Context;
import android.view.View;
import android.widget.AbsoluteLayout;
/**
* 动态生成控件基类
* Created by Neo on 2015/11/2 0002.
*/
public abstract class Generator {
public Generator() {
}
protected Context context;
public Generator(Context context, int x, int y, int width, int height) {
this.context = context;
this.setX(x);
this.setY(y);
this.setWidth(width);
this.setHeight(height);
}
private int x, y; //控件左上角坐标
private int width, height; //控件宽高
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
/**
* 获取生成的控件
*
* @return 生成好的控件
*/
public abstract View getView();
public abstract void clearMemory();
// public abstract void pause();
/**
* 获取在AbsoluteLayout中的布局参数,可根据需要进行覆盖
*
* @return
*/
public AbsoluteLayout.LayoutParams getLayoutParams() {
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(getWidth(), getHeight(), getX(), getY());
return params;
}
//dip转像素
public static int DipToPixels(Context context, int dip) {
final float SCALE = context.getResources().getDisplayMetrics().density;
float valueDips = dip;
int valuePixels = (int) (valueDips * SCALE + 0.5f);
return valuePixels;
}
//像素转dip
public static float PixelsToDip(Context context, int Pixels) {
final float SCALE = context.getResources().getDisplayMetrics().density;
float dips = Pixels / SCALE;
return dips;
}
}
接下来是一个ViewPager图片展示,原理都差不多,看懂一个就行了,这里我是使用了bannner框架,banner的使用方法我就不这里解释了 ,可以去github上找。
package com.etv.view.layout;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import com.etv.R;
import com.etv.util.banner.BannerUtil;
import com.youth.banner.Banner;
import java.util.List;
/***
* 加载图片资源
*/
public class ViewImageGenertrator extends Generator {
Context context;
View view;
List imageList;
public ViewImageGenertrator(Context context, int startX, int StartY, int width, int height, List imageList) {
super(context, startX, StartY, width, height);
this.imageList = imageList;
view = LayoutInflater.from(context).inflate(R.layout.view_image, null);
initView(view);
}
Banner banner_image;
BannerUtil bannerUtil;
private void initView(View view) {
banner_image = (Banner) view.findViewById(R.id.banner_image);
try {
if (bannerUtil != null) {
bannerUtil.stopPlay();
}
bannerUtil = new BannerUtil(context, banner_image, imageList);
bannerUtil.startPlay();
Log.i("cdl", "=====imageList==" + imageList.size());
} catch (Exception e) {
Log.i("cdl", "=====error==" + e.toString());
}
}
@Override
public View getView() {
return view;
}
@Override
public void clearMemory() {
if (imageList != null) {
imageList.clear();
}
}
}
下面是一个跑马灯的效果。
package com.etv.view.layout;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import com.etv.R;
import com.etv.view.MarqueeView;
/**
* 跑马灯位置
*/
public class ViewMatQueentestGenerte extends Generator {
View view;
private MarqueeView tv_marqueen;
public ViewMatQueentestGenerte(Context context, int x, int y, int width, int height, String text) {
super(context, x, y, width, height);
view = LayoutInflater.from(context).inflate(R.layout.view_marqueentest, null);
initView(view, text);
}
private void initView(View view, String text) {
tv_marqueen = (MarqueeView) view.findViewById(R.id.mMarqueeView);
tv_marqueen.setText(text);
tv_marqueen.startScroll();
}
@Override
public View getView() {
return view;
}
@Override
public void clearMemory() {
if (tv_marqueen != null) {
tv_marqueen.stopScroll();
}
}
}