关于自定义View,可以磊加控件 的宽高,并且有进入动画,
向自定义View动态加入控件
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import bwie.com.utils.SizeUtil;
public class MyView extends ViewGroup {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 得到子View的宽高
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int endWidth = 0;
int endHeight = 0;
int childCount = getChildCount();
if(childCount>0){
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
endHeight +=view.getMeasuredHeight();
measureChild(view,widthMeasureSpec,heightMeasureSpec);
}
}
endWidth = SizeUtil.SizeData(getContext());
setMeasuredDimension(endWidth,endHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = 0,top=0,right = 0,bottom=0;
int child = getChildCount();
for (int i = 0; i <child ; i++) {
View view = getChildAt(i);
view.layout(left,top,left + view.getMeasuredWidth(),top+view.getMeasuredHeight());
left += view.getMeasuredWidth();
top +=view.getMeasuredHeight();
if(left+view.getMeasuredWidth() > SizeUtil.SizeData(getContext())){
left=0;
}
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
TextView textView = (TextView) v;
Log.e("textView:","=="+textView.getText().toString());
Intent intent = new Intent(getContext(),MainActivity.class);
intent.putExtra("id",textView.getText().toString());
getContext().startActivity(intent);
}
});
view.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
removeView(v);
return true;
}
});
}
}
}
关于自定义View的Activity
import android.animation.ObjectAnimator;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import bwie.com.R;
import bwie.com.utils.SizeUtil;
public class ThreeActivity extends AppCompatActivity implements View.OnClickListener {
private Button add;
private int count = 0;
private MyView myView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_three);
initView();
}
private void initView() {
add = findViewById(R.id.but_add);
add.setOnClickListener(this);
myView = findViewById(R.id.myView);
}
@Override
public void onClick(View v) {
count++;
int width = SizeUtil.SizeData(this);
// Log.e("OPPOPOPO","==="+width);
TextView textView = new TextView(this);
textView.setText(count+"");
textView.setTextSize(16);
textView.setGravity(Gravity.CENTER);
textView.setTextColor(Color.BLACK);
ObjectAnimator objectAnimator = ObjectAnimator
.ofFloat(textView,"translationX",(width-width/3),0);
objectAnimator.setDuration(2000);
objectAnimator.start();
if(count == 1||count == 4||count == 7||count == 10||count == 13||count == 16||count == 19){
textView.setBackgroundColor(Color.RED);
}else if(count == 2||count == 5||count == 8||count == 11||count == 14||count == 17||count == 20){
textView.setBackgroundColor(Color.YELLOW);
}else {
textView.setBackgroundColor(Color.BLUE);
}
myView.addView(textView);
//View的参数
ViewGroup.LayoutParams params = textView.getLayoutParams();
params.width = width/3;
params.height = 70;
textView.setLayoutParams(params);
}
}
工具类参上:
判断网络是否链接的工具类,需要添加权限
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class NetUtil {
public static boolean isConn(Context context){
//1.得到系统服务
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
//2.得到网络信息类对象-需要添加权限
NetworkInfo info = manager.getActiveNetworkInfo();
//3.进行判断
if(info!=null && info.isAvailable()){//已经连接网络
return true;
}else{
return false;
}
}
}
OkHttp请求网络工具类
单例模式、二次封装、应用拦截器、get、post封装
import java.util.HashMap;
import java.util.Iterator;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
public class OkHttpUtils {
private static OkHttpUtils okHttpUtils;
private OkHttpClient okHttpClient;
private OkHttpUtils() {
okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
}
public static OkHttpUtils getINSTANCE(){
if(okHttpUtils == null){
okHttpUtils = new OkHttpUtils();
}
return okHttpUtils;
}
public void getGet(String str, Callback callback){
Request request = new Request.Builder()
.get()
.url(str)
.build();
okHttpClient.newCall(request).enqueue(callback);
}
public void getPost(String str, HashMap<String,String> map,Callback callback){
FormBody.Builder builder = new FormBody.Builder();
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
String value = map.get(key);
builder.add(key,value);
}
Request request = new Request.Builder()
.post(builder.build())
.url(str)
.build();
okHttpClient.newCall(request).enqueue(callback);
}
}
获得整个屏幕的宽度
自定义View时使用
import android.content.Context;
import android.util.DisplayMetrics;
public class SizeUtil {
public static int SizeData(Context context){
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return metrics.widthPixels;
}
}
MVP参上:
model:
import bwie.com.presenter.MyPresenterInterface;
import bwie.com.utils.OkHttpUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class MyModel {
public void getDate(String str, final MyPresenterInterface myPresenterInterface) {
OkHttpUtils.getINSTANCE().getGet(str, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful() && response.code() == 200) {
String s = response.body().string();
myPresenterInterface.onSuccess(s);
}
}
});
}
public void postDate(final String str, HashMap<String, String> map, final MyPresenterInterface myPresenterInterface) {
OkHttpUtils.getINSTANCE().getPost(str, map, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful() && response.code() == 200) {
String s = response.body().string();
myPresenterInterface.onSuccess(s);
}
}
});
}
}
presenter
解绑与绑定
字符串替换是因为请求的数据格式不对,重新修饰一下
import java.util.HashMap;
import bwie.com.model.MyModel;
import bwie.com.view.MyViewInterface;
public class MyPresenter implements MyPresenterInterface {
private MyModel myModel;
private MyViewInterface myViewInterface;
public MyPresenter(MyViewInterface myViewInterface) {
this.myModel = new MyModel();
atachView(myViewInterface);
}
/**
* 绑定
*
* @param myViewInterface
*/
public void atachView(MyViewInterface myViewInterface) {
this.myViewInterface = myViewInterface;
}
/**
* 解绑
*/
public void detachView() {
if (myViewInterface != null) {
myViewInterface = null;
}
}
public void getDate(String str) {
myModel.getDate(str, this);
}
public void postDate(String str, HashMap<String, String> map) {
myModel.postDate(str, map, this);
}
@Override
public void onSuccess(Object obj) {
String s = (String) obj;
String str = s.replace("null(", "").replace(")", "");
myViewInterface.onSuccess(str);
}
}
presenter的接口
public interface MyPresenterInterface {
void onSuccess(Object obj);
}
Activity的基类
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(setView());
initView();
initDate();
}
abstract void initView();
abstract void initDate();
abstract int setView();
}
view
继承基类的MainActivity
XRecyclerView实现刷新与加载,请求网络时进行判断,如果有网络,请求进行显示并进行数据库存储,如果没有网络链接,使用上次存到数据库中的数据进行处理与展示
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.widget.Toast;
import com.google.gson.Gson;
import com.jcodecraeer.xrecyclerview.XRecyclerView;
import java.util.HashMap;
import java.util.List;
import bwie.com.R;
import bwie.com.adapter.XRecyclerAdapter;
import bwie.com.common.Contants;
import bwie.com.db.DbHelper;
import bwie.com.model.BeanAll.NewsBean;
import bwie.com.presenter.MyPresenter;
import bwie.com.utils.NetUtil;
public class MainActivity extends BaseActivity implements MyViewInterface {
private XRecyclerView xrcv;
private int page = 5010;
private boolean isRefresh = true;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String s = (String) msg.obj;
Gson gson = new Gson();
NewsBean newsBean = gson.fromJson(s, NewsBean.class);
List<NewsBean.DataBean> list = newsBean.getData();
if(isRefresh){
adapter = new XRecyclerAdapter(list, MainActivity.this);
xrcv.setAdapter(adapter);
xrcv.refreshComplete();
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("json",s);
db.insert(DbHelper.DB_TABLE,null,contentValues);
}else{
if(adapter!=null){
adapter.loadMore(list);
}
xrcv.loadMoreComplete();
}
}
};
private MyPresenter presenter;
private DbHelper dbHelper;
private XRecyclerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
initView();
initDate();
}
@Override
void initView() {
xrcv = (XRecyclerView) findViewById(R.id.xrcv);
xrcv.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
xrcv.setItemAnimator(new DefaultItemAnimator());
xrcv.setPullRefreshEnabled(true);
xrcv.setLoadingMoreEnabled(true);
xrcv.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
isRefresh = true;
page = 5010;
request();
xrcv.refreshComplete();
}
@Override
public void onLoadMore() {
isRefresh = false;
page++;
request();
xrcv.loadMoreComplete();
}
});
}
@Override
void initDate() {
presenter = new MyPresenter(this);
dbHelper = new DbHelper(this);
request();
}
private void request() {
Intent intent = getIntent();
String id = intent.getExtras().getString("id");
page = 5010+Integer.parseInt(id);
if(NetUtil.isConn(this)){
HashMap<String, String> map = new HashMap<>();
map.put("type", page + "");
presenter.postDate(Contants.POST_URl, map);
}else{
Toast.makeText(this,"无网络链接!",Toast.LENGTH_SHORT).show();
String json = null;
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from news", null);
while (cursor.moveToNext()){
json = cursor.getString(cursor.getColumnIndex("json"));
}
NewsBean newsBean = new Gson().fromJson(json,NewsBean.class);
XRecyclerAdapter adapter = new XRecyclerAdapter(newsBean.getData(),MainActivity.this);
xrcv.setAdapter(adapter);
}
}
@Override
int setView() {
return R.layout.activity_main;
}
@Override
public void onSuccess(Object obj) {
String s = (String) obj;
Message msg = Message.obtain();
msg.obj = s;
handler.sendMessage(msg);
}
@Override
protected void onDestroy() {
super.onDestroy();
presenter.detachView();
}
}
view的接口:
public interface MyViewInterface {
void onSuccess(Object obj);
}
XRecyclerView的适配器,并且多条目加载,其中有长按删除:
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.jcodecraeer.xrecyclerview.XRecyclerView;
import java.util.List;
import bwie.com.R;
import bwie.com.common.Contants;
import bwie.com.model.BeanAll.NewsBean;
public class XRecyclerAdapter extends XRecyclerView.Adapter<XRecyclerView.ViewHolder> {
private List<NewsBean.DataBean> list;
private Context context;
public XRecyclerAdapter(List<NewsBean.DataBean> list, Context context) {
this.list = list;
this.context = context;
}
public void loadMore(List<NewsBean.DataBean> data){
if(list!=null){
list.addAll(data);
notifyDataSetChanged();
}
}
@NonNull
@Override
public XRecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if(viewType == Contants.TYPE1){
View view = View.inflate(context, R.layout.item_rcv1,null);
return new HolderType1(view);
}else{
View view = View.inflate(context, R.layout.item_rcv3,null);
return new HolderType3(view);
}
}
@Override
public void onBindViewHolder(@NonNull final XRecyclerView.ViewHolder holder, int position) {
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("确定删除吗?");
builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int p = holder.getLayoutPosition();
Log.e("Pos","p:"+p);
list.remove(p-1);
notifyItemRemoved(p);
}
});
builder.setNeutralButton("取消",null);
builder.show();
return true;
}
});
NewsBean.DataBean data = list.get(position);
if(holder instanceof HolderType1){
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType1) holder).img);
((HolderType1) holder).title.setText(data.getTopic());
((HolderType1) holder).time.setText(data.getDate()+" "+data.getSource());
}else if(holder instanceof HolderType3){
((HolderType3) holder).title.setText(data.getTopic());
((HolderType3) holder).time.setText(data.getDate()+" "+data.getSource());
if(data.getMiniimg()!=null && data.getMiniimg().size()>0){
if(data.getMiniimg().size() == 1){
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType3) holder).img1);
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType3) holder).img2);
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType3) holder).img3);
}else if(data.getMiniimg().size() == 2){
Glide.with(context).load(data.getMiniimg().get(1).getSrc()).into(((HolderType3) holder).img1);
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType3) holder).img2);
Glide.with(context).load(data.getMiniimg().get(1).getSrc()).into(((HolderType3) holder).img3);
}else {
Glide.with(context).load(data.getMiniimg().get(0).getSrc()).into(((HolderType3) holder).img1);
Glide.with(context).load(data.getMiniimg().get(1).getSrc()).into(((HolderType3) holder).img2);
Glide.with(context).load(data.getMiniimg().get(2).getSrc()).into(((HolderType3) holder).img3);
}
}
}
}
@Override
public int getItemViewType(int position) {
return position%3==2?Contants.TYPE1:Contants.TYPE3;
}
@Override
public int getItemCount() {
return list.size();
}
class HolderType1 extends XRecyclerView.ViewHolder{
ImageView img;
TextView title;
TextView time;
public HolderType1(View itemView) {
super(itemView);
img = itemView.findViewById(R.id.rcv1_img);
title = itemView.findViewById(R.id.rcv1_text);
time = itemView.findViewById(R.id.rcv1_ts);
}
}
class HolderType3 extends XRecyclerView.ViewHolder{
ImageView img1,img2,img3;
TextView title,time;
public HolderType3(View itemView) {
super(itemView);
img1 = itemView.findViewById(R.id.rcv3_img1);
img2 = itemView.findViewById(R.id.rcv3_img2);
img3 = itemView.findViewById(R.id.rcv3_img3);
title = itemView.findViewById(R.id.rcv3_text);
time = itemView.findViewById(R.id.rcv3_ts);
}
}
}
关于数据库的创建,表的创建:
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DbHelper extends SQLiteOpenHelper {
private static String DB_NAME = "news.db";
public static String DB_TABLE = "news";
public DbHelper(Context context) {
super(context, DB_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table "+DB_TABLE+" (_id Integer PRIMARY KEY,json text) ";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
全局需要:
public class Contants {
public static String POST_URl = "http://ttpc.dftoutiao.com/jsonpc/refresh";
public static int TYPE1 = 1;
public static int TYPE3 = 3;
}
布局文件:
多条目1:
<?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:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="@+id/rcv1_img"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_weight="2"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="7">
<TextView
android:id="@+id/rcv1_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="上的讲话不舒服就k看到世讲话不舒服就k看到世界很疯狂就"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/rcv1_ts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rcv1_text"
android:layout_marginTop="10dp"
android:text="即使对方"
android:textSize="12dp" />
</RelativeLayout>
</LinearLayout>
多条目2:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
<TextView
android:id="@+id/rcv3_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="肯德基和疯狂的女人给会计的女人给会计年度浮亏加拿大"
android:textSize="16dp"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/lin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/rcv3_text"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/rcv3_img1"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<ImageView
android:id="@+id/rcv3_img2"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<ImageView
android:id="@+id/rcv3_img3"
android:layout_width="0dp"
android:layout_height="70dp"
android:layout_weight="1"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
<TextView
android:id="@+id/rcv3_ts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/lin"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:text="的疯狂就是如果你 看到妇女你"
android:textSize="12dp" />
</RelativeLayout>
权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
依赖:
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.github.bumptech.glide:glide:4.7.1'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.jcodecraeer:xrecyclerview:1.5.9'