Android自定義View實現動畫流式佈局及點擊添加功能

動畫添加流式佈局點擊動畫添加

上一篇已經發表了流式佈局點擊添加功能這裏就不用了,需要的可以去上一篇博客查看

步入正題

在build。gradle中配置以下:

//Gson依賴
implementation ‘com.google.code.gson:gson:2.8.5’

//volley請求框架
implementation ‘com.android.volley:volley:1.1.1’

首先配置一個全局異常捕獲,首先創建一個異常捕獲的一個類

public class MyHandle implements Thread.UncaughtExceptionHandler {

@Override
public void uncaughtException(@NonNull Thread thread,
 @NonNull Throwable throwable) {
    Log.e("e=====",""+throwable);
}

}

接着創建一個App的類進行上下文配置,及異常捕獲配置

public class App extends Application {
public static Context context;

@Override
public void onCreate() {
    super.onCreate();
   context= getApplicationContext();

  MyHandle myHandle = new MyHandle();
  Thread.setDefaultUncaughtExceptionHandler(myHandle);
}

public static Context getContext(){
    return context;
}

}

之後在清單文件中配置完成

android:name=".app.App"

創建一個Volley封裝工具類GET請求

public class VolleyUtils {
private static VolleyUtils volley;
private final RequestQueue requestQueue;

private VolleyUtils() {
    requestQueue = Volley.newRequestQueue(App.getContext());
}

public static VolleyUtils getInstance() {
    if (volley==null){
        synchronized (VolleyUtils.class){
            if (volley==null){
                volley=new VolleyUtils();
            }
        }
    }
    return volley;
}

public void doGet(String s, final VolleyCallBack volleyCallBack){
    StringRequest stringRequest = new StringRequest(StringRequest.Method.GET,s, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            if (volleyCallBack!=null){
            volleyCallBack.success(response);
        }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
                if (volleyCallBack!=null){

            volleyCallBack.failure(error);
                }
        }
    });
    requestQueue.add(stringRequest);
}

public interface VolleyCallBack{
    void success(String s);
    void failure(Throwable throwable);
}

}

根據json串創建Entity類這裏就不展示了

之後進行契約類MVP配置

契約類配置如下

public interface INewsContract {
interface IModel{
interface ModelCallBack{
void success(ShopEntity shopEntity);
void failure(Throwable throwable);
}
void getList(String url,ModelCallBack modelCallBack);
}

interface IView{
    void success(ShopEntity shopEntity);
    void failure(Throwable throwable);
}
interface IPresenter{
    void getList(String url);
}

}

Model層配置如下

public class IModel implements INewsContract.IModel {
@Override
public void getList(String url, final ModelCallBack modelCallBack) {
VolleyUtils.getInstance().doGet(url, new VolleyUtils.VolleyCallBack() {
@Override
public void success(String s) {
ShopEntity shopEntity = new Gson().fromJson(s, ShopEntity.class);
modelCallBack.success(shopEntity);
}

        @Override
        public void failure(Throwable throwable) {
            modelCallBack.failure(throwable);
        }
    });
}

}

P層配置如下

public class IPresenter implements INewsContract.IPresenter {

INewsContract.IView iView;
private final IModel iModel;

public IPresenter(INewsContract.IView iView) {
    this.iView = iView;
    iModel = new IModel();
}

@Override
public void getList(String url) {
    iModel.getList(url, new INewsContract.IModel.ModelCallBack() {
        @Override
        public void success(ShopEntity shopEntity) {
            iView.success(shopEntity);
        }

        @Override
        public void failure(Throwable throwable) {
            iView.failure(throwable);
        }
    });
}

}
V層配置在顯示頁面上,這裏先不配置

配置Activity的基類

public abstract class BaseActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(layoutId());
    initView();
    initData();
}

protected abstract void initData();

protected abstract void initView();

protected abstract int layoutId();

}

配置Fragment的基類

public abstract class BaseFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View inflate = inflater.inflate(layoutId(), container, false);
    initView(inflate);
    return inflate;
}

protected abstract void initView(View inflate);

protected abstract int layoutId();

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    initData();
}

protected abstract void initData();

}

配置流式佈局,如下

public class FlowLayout extends ViewGroup {

private int color;

public FlowLayout(Context context) {
    super(context);
    init(context,null);
}

public FlowLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context,attrs);
}

public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context,attrs);
}

//自定義屬性配置
public void init(Context context, AttributeSet attrs){
TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.FlowLayout);
color = typedArray.getColor(R.styleable.FlowLayout_myTagColor, Color.YELLOW);

}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int left=0;
    int top=0;
    int right=0;
    int buttom=0;
    int childCount = getChildCount();
    if (childCount>0){
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);
            childAt.measure(0,0);
            int measuredHeight = childAt.getMeasuredHeight();
            int measuredWidth = childAt.getMeasuredWidth();
            right=left+measuredWidth;
            if (right>getWidth()){
                left=0;
                right=left+measuredWidth;
                top=buttom+10;
            }
            buttom=top+measuredHeight;
            childAt.layout(left,top,right,buttom);
            left+=measuredWidth+10;
        }
    }



}

//添加子控件
public void addChildView(List<ShopEntity.ResultBean> result) {
if (result!=null&&result.size()>0) {
for (ShopEntity.ResultBean resultBean : result) {
TextView textView = new TextView(getContext());
textView.setPadding(10,0,10,0);
textView.setText(resultBean.getCommodityName());
textView.setBackgroundResource(R.drawable.sss);
textView.setTextColor(color);
textView.setTextSize(12);
//添加動畫效果
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,“rotation”,0,360);
objectAnimator.setDuration(1000);
objectAnimator.start();
addView(textView);
}
}
}
}

配置流式佈局的xml

<com.bawei.songjiahao.lianxi_1213.widget.FlowLayout
app:myTagColor="#ff0001"
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:id="@+id/flow"></com.bawei.songjiahao.lianxi_1213.widget.FlowLayout>

配置組合控件,並綁定流式佈局

public class SearchLayout extends LinearLayout {
public SearchLayout(Context context) {
super(context);
init(context);
}

public SearchLayout(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public SearchLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}

public  void init(Context context){
    View inflate = View.inflate(context, R.layout.layout_flow, null);
    addView(inflate);
}

}

配置自定義屬性如下圖

在這裏插入圖片描述

接下來配置一個RadioGroup和Viewpager實現一個點擊滑動的一個簡單效果配置如下

在主頁中配置如下

<androidx.viewpager.widget.ViewPager
android:layout_width=“match_parent”
android:layout_height=“0dp”
android:layout_weight=“9”
android:id="@+id/vp"></androidx.viewpager.widget.ViewPager>




配置背景選擇器

在這裏插入圖片描述
在這裏插入圖片描述

配置首頁xml佈局,將組合控件插入,及點擊按鈕

在這裏插入圖片描述

在首頁中配置上V層

public class HomeFragment extends BaseFragment implements INewsContract.IView {

private FlowLayout fl;
private SearchLayout search;
private Button bt;
private IPresenter iPresenter;

@Override
protected void initView(View inflate) {
   search=inflate.findViewById(R.id.search);
    fl = inflate.findViewById(R.id.flow);
    bt = inflate.findViewById(R.id.bt);
    bt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String k="關鍵詞";
            String encode = URLEncoder.encode(k);//編碼配置
            iPresenter.getList("   json串“+encode+”  ");
        }
    });
}

@Override
protected int layoutId() {
    return R.layout.fragment_home;
}

@Override
protected void initData() {
    iPresenter = new IPresenter(this);
    String k="關鍵詞";
    String encode = URLEncoder.encode(k);//編碼配置
    iPresenter.getList("   json串“+encode+”  ");
}

@Override
public void success(ShopEntity shopEntity) {
    List<ShopEntity.ResultBean> result = shopEntity.getResult();
    fl.addChildView(result);
}

@Override
public void failure(Throwable throwable) {

}

}

在其他頁xml中配置一個textView

在這裏插入圖片描述

其他頁中接口動態賦值給TextView,如下

public class OtherFragment extends BaseFragment {

private TextView other_tv;

@Override
protected void initView(View inflate) {
    other_tv = inflate.findViewById(R.id.other_tv);
}

@Override
protected int layoutId() {
    return R.layout.fragment_other;
}

@Override
protected void initData() {
    Bundle arguments = getArguments();
    String key = arguments.getString("key");
    other_tv.setText(key);
    other_tv.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(other_tv, "scaleX", 0f, 5f);
            ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(other_tv, "scaleY", 0f, 5f);
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.play(objectAnimator).with(objectAnimator1);
            animatorSet.setDuration(2000);
            animatorSet.start();
        }
    });

}

public static OtherFragment getInstance(String value) {
    OtherFragment otherFragment = new OtherFragment();
    Bundle bundle = new Bundle();
    bundle.putString("key",value);
    otherFragment.setArguments(bundle);
    return otherFragment;
}

}

在主佈局中配置如下

public class MainActivity extends BaseActivity {

private ViewPager vp;
private RadioGroup rg;
private List<Fragment> list;


@Override
protected void initView() {
    vp = findViewById(R.id.vp);
    rg = findViewById(R.id.rg);
    list = new ArrayList<>();
    HomeFragment homeFragment = new HomeFragment();
    list.add(homeFragment);
    OtherFragment otherFragment = OtherFragment.getInstance("北京");
    list.add(otherFragment);
    OtherFragment otherFragment1 = OtherFragment.getInstance("我的");
    list.add(otherFragment1);
    vp.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return list.get(position);
        }

        @Override
        public int getCount() {
            return list.size();
        }
    });
    vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            rg.check(rg.getChildAt(position).getId());
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
    rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup radioGroup, int i) {
            switch (i){
                case R.id.rb_first:
                    vp.setCurrentItem(0);
                    break;
                case R.id.rb_beijing:
                    vp.setCurrentItem(1);
                    break;
                case R.id.rb_my:
                    vp.setCurrentItem(2);
                    break;
            }
        }
    });
}

@Override
protected void initData() {

}

@Override
protected int layoutId() {
    return R.layout.activity_main;
}

}

這樣基本就完成了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章