├── .gitignore ├── README.md └── lineGridView ├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── tamic │ │ └── linegridview │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── plugin.json │ ├── java │ │ └── com │ │ │ └── tamic │ │ │ └── linegridview │ │ │ ├── BaseGridView.java │ │ │ ├── MainActivity.java │ │ │ ├── PaAbsAdapter.java │ │ │ ├── PaAbsGridView.java │ │ │ ├── PluginAdapter.java │ │ │ ├── PluginConfigModle.java │ │ │ ├── PluginGridView.java │ │ │ ├── PluginGridViewItem.java │ │ │ ├── PluginGridview2.java │ │ │ ├── ViewUtils.java │ │ │ ├── base │ │ │ ├── BaseBean.java │ │ │ └── BaseResponse.java │ │ │ ├── model │ │ │ └── PluginData.java │ │ │ └── util │ │ │ └── JsonUtil.java │ └── res │ │ ├── drawable │ │ ├── home_divider_day.xml │ │ ├── home_divider_night.xml │ │ ├── home_item_bg.xml │ │ ├── home_item_night_bg.xml │ │ ├── home_navi_divider.png │ │ └── home_navi_divider_night.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── tamic │ └── linegridview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LineGridView 2 | 带分割线的GridView 3 | 4 | ![](http://img.blog.csdn.net/20160906195839413?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 5 | 6 | 适合微信和支付宝做插件模块,业务支持url, 支持app, 支持plugin 7 | 8 | PuginLoader 可见:https://github.com/NeglectedByBoss/PluginLoader 9 | -------------------------------------------------------------------------------- /lineGridView/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /lineGridView/.idea/.name: -------------------------------------------------------------------------------- 1 | lineGridView -------------------------------------------------------------------------------- /lineGridView/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /lineGridView/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /lineGridView/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lineGridView/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /lineGridView/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /lineGridView/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lineGridView/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /lineGridView/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /lineGridView/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.tamic.linegridview" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.4.0' 26 | compile 'com.squareup.picasso:picasso:2.5.2' 27 | compile 'com.squareup.okhttp3:okhttp:3.3.1' 28 | compile 'com.squareup.okhttp3:logging-interceptor:3.3.1' 29 | 30 | compile 'com.alibaba:fastjson:1.2.12' 31 | } 32 | -------------------------------------------------------------------------------- /lineGridView/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Users\liuyongkui726\AppData\Local\Android\android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /lineGridView/app/src/androidTest/java/com/tamic/linegridview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /lineGridView/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/assets/plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 0, 3 | "msg": "ok", 4 | "data": { 5 | "count": 3, 6 | "list": [ 7 | { 8 | "id": 123, 9 | "type": 1, 10 | "packageName": "com.example.pluginhelloworld", 11 | "description": "一款租房插件,海量房源等你看", 12 | "pluginName": "Tamic", 13 | "version": 1, 14 | "mainActivity": "com.example.pluginhelloworld.WelcomeActivity", 15 | "isEnabled": 0, 16 | "appIcon": "http://img.hexun.com/2009-05-01/117287830.jpg", 17 | "downUrl": "url" 18 | }, 19 | { 20 | "id": 1234, 21 | "type": 1, 22 | "packageName": "com.example.liuyongkui.pluginapk", 23 | "description": "一款测试插件,test看", 24 | "pluginName": "插件2", 25 | "version": 1, 26 | "mainActivity": "com.example.liuyongkui.pluginapk.MainActivity", 27 | "isEnabled": 0, 28 | "appIcon": "http://image.cnwest.com/attachement/jpg/site1/20110507/001372d8a36f0f2f4c953a.jpg", 29 | "downUrl": "url" 30 | }, 31 | 32 | { 33 | "id": 12358, 34 | "type": 3, 35 | "packageName": "", 36 | "description": "这是网站", 37 | "pluginName": "chajian", 38 | "version": 1, 39 | "mainActivity": " ", 40 | "isEnabled": 0, 41 | "appIcon": "http://ecma.bdimg.com/lego-mat/4b69e8fef70606db27815c2b13c62497_222_222.png", 42 | "downUrl": "http://www.baidu.com/" 43 | }, 44 | { 45 | "id": 1235, 46 | "type": 1, 47 | "packageName": "com.example.pluginhelloworld", 48 | "description": "一款XX插件,", 49 | "pluginName": "插件3", 50 | "version": 1, 51 | "mainActivity": "com.example.pluginhelloworld.WelcomeActivity", 52 | "isEnabled": 0, 53 | "appIcon": "http://img3.yxlady.com/yl/UploadFiles_5361/20150528/20150528050208705.jpg", 54 | "downUrl": "this is url" 55 | }, 56 | 57 | { 58 | "id": 1236, 59 | "type": 2, 60 | "packageName": "com.tamic.retrofit", 61 | "description": "一款网络神器", 62 | "pluginName": "网路库", 63 | "version": 1, 64 | "mainActivity": "com.pinganfang.ananzu.LoadingActivity", 65 | "isEnabled": 0, 66 | "appIcon": "http://img0.imgtn.bdimg.com/it/u=517288495,4076033457&fm=21&gp=0.jpg", 67 | "downUrl": "http Url" 68 | }, 69 | 70 | { 71 | "id": 1237, 72 | "type": 3, 73 | "packageName": "", 74 | "description": "海量视频随你看", 75 | "pluginName": "爱奇艺", 76 | "version": 1, 77 | "mainActivity": "com.example.pluginhelloworld.WelcomeActivity", 78 | "isEnabled": 0, 79 | "appIcon": "http://juxiao.mediav.com/blog/wp-content/uploads/2013/08/%E7%88%B1%E5%A5%87%E8%89%BAlogo.png", 80 | "downUrl": "http://m.iqiyi.com" 81 | } 82 | ] 83 | } 84 | } -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/BaseGridView.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.View.OnClickListener; 6 | import android.view.View.OnLongClickListener; 7 | 8 | 9 | /** 10 | * 基础 baseGridview 11 | * 提供事件绑定操作 12 | * Created by LIUYONGKUI on 2016-03-03. 13 | */ 14 | public abstract class BaseGridView extends PaAbsGridView implements OnClickListener, OnLongClickListener{ 15 | 16 | /** 17 | * @param context 上下文 18 | * @param adapter 适配器 19 | */ 20 | public BaseGridView(Context context, PaAbsAdapter adapter) { 21 | this(context, adapter, -1); 22 | } 23 | 24 | /** 25 | * @param context 上下文 26 | * @param adapter 适配器 27 | * @param aCount 列数(默认3) 28 | */ 29 | public BaseGridView(Context context, PaAbsAdapter adapter, int aCount) { 30 | 31 | super(context, adapter, aCount <= 0 ? -1 : aCount); 32 | 33 | } 34 | 35 | @Override 36 | public void layoutItem(View aChild, int aPos, boolean aIsAnim) { 37 | super.layoutItem(aChild, aPos, aIsAnim); 38 | aChild.setOnClickListener(this); 39 | aChild.setOnLongClickListener(this); 40 | } 41 | 42 | 43 | @Override 44 | public void onClick(View v) { 45 | onItemClick(v); 46 | } 47 | 48 | @Override 49 | public boolean onLongClick(View v) { 50 | return onItemLongClick(v); 51 | } 52 | 53 | /** 54 | * item 短按事件 55 | * @param v 56 | */ 57 | public abstract void onItemClick(View v); 58 | 59 | /** 60 | * item 长按事件 61 | * @param v 62 | */ 63 | public abstract boolean onItemLongClick(View v); 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.content.Context; 4 | import android.support.v7.app.ActionBar; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.alibaba.fastjson.JSON; 13 | import com.alibaba.fastjson.TypeReference; 14 | import com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer; 15 | import com.squareup.picasso.Picasso; 16 | import com.tamic.linegridview.base.BaseResponse; 17 | import com.tamic.linegridview.model.PluginData; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.Closeable; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.InputStreamReader; 24 | import java.lang.reflect.UndeclaredThrowableException; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | public class MainActivity extends AppCompatActivity { 29 | 30 | private Context mContext; 31 | private PluginAdapter mPluginAdapter; 32 | 33 | private PluginGridView mPluginsView; 34 | 35 | private BaseGridView mPluginsView2; 36 | 37 | private List mModles; 38 | 39 | private Picasso mPicasso; 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | //setContentView(R.layout.activity_main); 45 | 46 | ViewGroup inflate = (ViewGroup) getLayoutInflater().inflate(R.layout.activity_main, null); 47 | 48 | 49 | mContext = MainActivity.this; 50 | mPicasso = Picasso.with(mContext); 51 | init(); 52 | inflate.addView(mPluginsView); 53 | 54 | setContentView(inflate); 55 | mPluginsView.refreshViews(); 56 | 57 | 58 | 59 | 60 | } 61 | 62 | private void init() { 63 | 64 | mModles = loadPluginData(); 65 | mPluginAdapter = new PluginAdapter(mContext, mPicasso, mModles); 66 | mPluginsView = new PluginGridView(mContext, mPluginAdapter); 67 | mPluginsView.setIsDividerEnable(true); 68 | mPluginsView.setColCount(3); 69 | // mPluginsView.setAdapter(mPluginAdapter);*/ 70 | //mPluginsView = new PluginGridView(mContext, mPluginAdapter); 71 | //mPluginsView.setColumn(3); 72 | mPluginAdapter.notifyDataSetChanged(); 73 | 74 | 75 | 76 | } 77 | 78 | 79 | private ArrayList loadPluginData() { 80 | 81 | return (ArrayList) getPlugins(); 82 | 83 | 84 | } 85 | 86 | 87 | /** 88 | * 模拟数据 89 | */ 90 | public List getPlugins() { 91 | 92 | String result= getFromAssets(mContext, "plugin.json"); 93 | 94 | TypeReference> type = new TypeReference>(){}; 95 | if (TextUtils.isEmpty(result)) { 96 | throw new NullPointerException( "result == null"); 97 | } 98 | BaseResponse response = JSON.parseObject(result, type); 99 | 100 | Log.d(">>>>>>>>>>", response.getData().getList().toString()+""); 101 | Log.d(">>>>>>>>>>", response.getData().getList().size()+""); 102 | 103 | 104 | 105 | return response.getData().getList(); 106 | } 107 | 108 | 109 | 110 | // 读取assets文件夹的文件 111 | public static String getFromAssets(Context context, String fileName) { 112 | BufferedReader reader = null; 113 | try { 114 | InputStream in = context.getResources().getAssets().open(fileName); 115 | reader = new BufferedReader(new InputStreamReader(in)); 116 | 117 | char[] buf = new char[1024]; 118 | int count = 0; 119 | StringBuffer sb = new StringBuffer(in.available()); 120 | while ((count = reader.read(buf)) != -1) { 121 | String readData = String.valueOf(buf, 0, count); 122 | sb.append(readData); 123 | } 124 | 125 | return sb.toString(); 126 | } catch (Exception e) { 127 | e.printStackTrace(); 128 | } finally { 129 | closeStream(reader); 130 | } 131 | 132 | return null; 133 | 134 | } 135 | 136 | private static void closeStream(Closeable stream) { 137 | if (stream != null) { 138 | try { 139 | stream.close(); 140 | } catch (IOException e) { 141 | e.printStackTrace(); 142 | } 143 | } 144 | } 145 | 146 | 147 | } 148 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PaAbsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * BaseAdapter上封装了一层, 只需实现getView(int position, View convertView, ViewGroup parent)方法 14 | * 供Listview,gridView使用 15 | * @author LIUYONGKUI726 16 | * 17 | * @param 泛型 18 | */ 19 | public abstract class PaAbsAdapter extends BaseAdapter { 20 | public ArrayList mList = new ArrayList(); 21 | public Context mContext; 22 | 23 | public PaAbsAdapter(Context context, List list) { 24 | mContext = context; 25 | if (list != null) { 26 | mList.addAll(list); 27 | } 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | return mList == null ? 0 : mList.size(); 33 | } 34 | 35 | @Override 36 | public Object getItem(int position) { 37 | return mList == null ? null : mList.get(position); 38 | } 39 | 40 | @Override 41 | public long getItemId(int position) { 42 | return position; 43 | } 44 | 45 | @Override 46 | public abstract View getView(int position, View convertView, ViewGroup parent); 47 | 48 | /** 49 | * 更新ListView 50 | * 51 | * @param list 52 | */ 53 | public void notifyDataSetChanged(ArrayList list) { 54 | if (mList != list) { 55 | mList.clear(); 56 | if (list != null) { 57 | mList.addAll(list); 58 | } 59 | } 60 | if (mContext != null) { 61 | ((Activity)mContext).runOnUiThread(new Runnable() { 62 | 63 | @Override 64 | public void run() { 65 | notifyDataSetChanged(); 66 | } 67 | }); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PaAbsGridView.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Filename: BdHomeGridView.java 3 | * Description: 4 | * Copyright: Baidu MIC Copyright(c)2011 5 | * 6 | * @author: Jacob 7 | * @version: 1.0 8 | * Create at: 2013-7-3 下午4:25:45 9 | *

10 | * Modification History: 11 | * Date Author Version Description 12 | * ------------------------------------------------------------------ 13 | * 2015-6-16 Jacob 1.0 1.0 Version 14 | */ 15 | package com.tamic.linegridview; 16 | 17 | import android.content.Context; 18 | import android.database.DataSetObserver; 19 | import android.graphics.Canvas; 20 | import android.graphics.Paint; 21 | import android.graphics.Rect; 22 | import android.graphics.drawable.Drawable; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.BaseAdapter; 26 | import android.widget.FrameLayout; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | /** 32 | * 宫格视图抽象类 其子类为baseGridview 33 | * 提供最基本的绘制和属性初始化工作,添加删除工作以及条目 34 | * @author LIUYONGKUI 35 | */ 36 | public abstract class PaAbsGridView extends ViewGroup { 37 | 38 | /** 39 | * 视图holder的标志,用于标记View中的tag 40 | */ 41 | public static final int VIEW_HOLDER_TAG = 0x0fffff00; 42 | 43 | /** 44 | * 默认列数 45 | */ 46 | public static final int DEF_COLCOUNT = 3; 47 | 48 | /** 49 | * 行数 50 | */ 51 | private int mRowCount; 52 | /** 53 | * 列数 54 | */ 55 | private int mColCount; 56 | /** 57 | * 宫格宽度 58 | */ 59 | private float mCellWidth; 60 | /** 61 | * 宫格高度 62 | */ 63 | private int mCellHeight; 64 | /** 65 | * 临时区域 66 | */ 67 | private Rect mAssistRect = new Rect(); 68 | /** 69 | * 插槽 70 | */ 71 | private FrameLayout mSlotView; 72 | /** 73 | * 插槽的偏移量: y 74 | */ 75 | private int mSlotOffsetY; 76 | /** 77 | * 插槽的偏移行 78 | */ 79 | private int mSlotOffsetRow; 80 | /** 81 | * 分割线是否显示 82 | */ 83 | private boolean mIsDividerEnable; 84 | /** 85 | * 分割线 86 | */ 87 | private int mDividerWidth; 88 | /** 89 | * 交叉线行数 90 | */ 91 | private int mDividerRow; 92 | /** 93 | * 交叉线列数 94 | */ 95 | private int mDividerCol; 96 | /** 97 | * 分割线图片(白天) 98 | */ 99 | private Drawable mDividerDay; 100 | /** 101 | * 分割线图片(夜晚) 102 | */ 103 | private Drawable mDividerNight; 104 | /** 105 | * 数据适配器 106 | */ 107 | private BaseAdapter mAdapter; 108 | 109 | /** 110 | * 构造函数 111 | * 112 | * @param context 上下文 113 | * @param aAdapter adapter 114 | * @param aColCount 列数 115 | */ 116 | public PaAbsGridView(Context context, BaseAdapter aAdapter, int aColCount) { 117 | super(context); 118 | 119 | // 基本属性 120 | this.setWillNotDraw(false); 121 | mColCount = aColCount; 122 | mAdapter = aAdapter; 123 | mAdapter.registerDataSetObserver(new BdCellDataObserver()); 124 | 125 | // 视图属性 126 | mCellHeight = getCellHeight(); 127 | mDividerWidth = getDividerWidthDef(); 128 | mDividerDay = getDividerDay(); 129 | mDividerNight = getDividerDay(); 130 | 131 | // 刷新视图 132 | refreshViews(); 133 | } 134 | 135 | 136 | 137 | public void setAdapter(BaseAdapter mAdapter) { 138 | this.mAdapter = mAdapter; 139 | } 140 | 141 | 142 | public void setColCount(int mColCount) { 143 | this.mColCount = mColCount; 144 | } 145 | 146 | /** 147 | * 初始化视图 148 | */ 149 | public void refreshViews() { 150 | 151 | if (mSlotView == null) { 152 | mSlotView = new FrameLayout(getContext()); 153 | mSlotOffsetRow = 3; 154 | } 155 | 156 | final List cacheList = new ArrayList(); 157 | for (int i = 0; i < getIconViewCount(); i++) { 158 | cacheList.add(getIconView(i)); 159 | } 160 | 161 | removeAllIconViews(); 162 | 163 | // 添加单元项 164 | for (int i = 0; i < mAdapter.getCount(); i++) { 165 | addItemView(queryCacheItemView(cacheList, i), false); 166 | } 167 | 168 | cacheList.clear(); 169 | } 170 | 171 | /** 172 | * getDrviderDay 173 | * @return 174 | */ 175 | protected Drawable getDividerDay() { 176 | return getResources().getDrawable(R.drawable.home_divider_day); 177 | } 178 | 179 | 180 | /** 181 | * getDrivderNight 182 | * @return 183 | */ 184 | protected Drawable getDividerNight() { 185 | return getResources().getDrawable(R.drawable.home_divider_night); 186 | } 187 | 188 | 189 | /** 190 | * @return 适配器 191 | */ 192 | public BaseAdapter getAdapter() { 193 | return mAdapter; 194 | } 195 | 196 | /** 197 | * @param aIsEnable 分割线是否有效 198 | */ 199 | public void setIsDividerEnable(boolean aIsEnable) { 200 | mIsDividerEnable = aIsEnable; 201 | } 202 | 203 | /** 204 | * 获取缓存的单元视图 205 | * 206 | * @param aCacheList 缓存列表 207 | * @param aDataIndex 数据索引 208 | * @return 单元视图 209 | */ 210 | private View queryCacheItemView(List aCacheList, int aDataIndex) { 211 | final int count = ((aCacheList != null) ? aCacheList.size() : 0); 212 | 213 | View cacheView = null; 214 | 215 | // 寻找数据项匹配的单元视图 216 | Object item = mAdapter.getItem(aDataIndex); 217 | if (item != null) { 218 | for (int i = 0; i < count; i++) { 219 | View itemView = aCacheList.get(i); 220 | Object itemData = getViewHolder(itemView).getData(); 221 | if ((itemData != null) && (itemData.equals(item))) { 222 | aCacheList.remove(i); 223 | cacheView = itemView; 224 | break; 225 | } 226 | } 227 | } 228 | 229 | // 寻找类型匹配的单元视图 230 | View targetView = mAdapter.getView(aDataIndex, cacheView, null); 231 | getViewHolder(targetView).setData(item); 232 | return targetView; 233 | } 234 | 235 | /** 236 | * 往插槽里填充视图 237 | * 238 | * @param aView 视图 239 | */ 240 | public void addToSlot(View aView) { 241 | if ((aView != null) && (mSlotView.indexOfChild(aView) < 0)) { 242 | mSlotView.addView(aView, 243 | new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); 244 | } 245 | } 246 | 247 | /** 248 | * 添加单元格视图 249 | * 250 | * @param aIconView 图标单元格视图 251 | */ 252 | public void addIconView(View aIconView) { 253 | addView(aIconView); 254 | } 255 | 256 | /** 257 | * 添加单元格视图 258 | * 259 | * @param aIconView 单元格视图 260 | * @param aIconIndex 位置 261 | */ 262 | public void addIconView(View aIconView, int aIconIndex) { 263 | addView(aIconView, aIconIndex + 1); 264 | } 265 | 266 | /** 267 | * 移除单元格视图 268 | * 269 | * @param aIconView 单元格视图 270 | */ 271 | public void removeIconView(View aIconView) { 272 | removeView(aIconView); 273 | } 274 | 275 | /** 276 | * @return 单元格视图的总个数 277 | */ 278 | public int getIconViewCount() { 279 | return getChildCount() - 1; 280 | } 281 | 282 | /** 283 | * @param aIndex 索引 284 | * @return 单元格视图 285 | */ 286 | public View getIconView(int aIndex) { 287 | return getChildAt(aIndex + 1); 288 | } 289 | 290 | /** 291 | * 移除所有的单元格视图 292 | */ 293 | public void removeAllIconViews() { 294 | removeAllViews(); 295 | addView(mSlotView); 296 | } 297 | 298 | /** 299 | * 释放所有视图资源 300 | */ 301 | public void releaseAllViews() { 302 | removeAllViews(); 303 | } 304 | 305 | @Override 306 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 307 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 308 | 309 | // 获取给定尺寸 310 | int width = MeasureSpec.getSize(widthMeasureSpec); 311 | int nChildCount = getIconViewCount(); 312 | 313 | // 计算总行数和总列数 314 | mColCount = getColCount(); 315 | int row = nChildCount / mColCount; 316 | int col = nChildCount % mColCount; 317 | mRowCount = ((col == 0) ? row : row + 1); 318 | 319 | // 计算单元格尺寸 320 | int dividerW = getDividerWidth() * (mColCount + 1); 321 | mCellWidth = 1.0f * (width - getPaddingLeft() - getPaddingRight() - dividerW) / mColCount; 322 | 323 | // 遍历子view的尺寸设置 324 | for (int i = 0; i < nChildCount; i++) { 325 | View child = getIconView(i); 326 | child.measure((int) mCellWidth, (int) mCellHeight); 327 | } 328 | 329 | // slot 330 | int slotHeightMeasureSpec = 331 | getChildMeasureSpec(heightMeasureSpec, 0, LayoutParams.WRAP_CONTENT); 332 | mSlotView.measure(widthMeasureSpec, slotHeightMeasureSpec); 333 | int slotRow = getSlotRow(); 334 | mSlotOffsetY = (int) (slotRow * mCellHeight + (slotRow + 1) * getDividerWidth()); 335 | 336 | // 计算总尺寸 337 | int nViewHeight = Math.round(mRowCount * mCellHeight + (mRowCount + 1) * getDividerWidth()); 338 | nViewHeight = nViewHeight + mSlotView.getMeasuredHeight(); 339 | if (slotRow < mRowCount && mSlotView.getMeasuredHeight() > 0) { 340 | nViewHeight = nViewHeight + getDividerWidth(); 341 | } 342 | nViewHeight = nViewHeight + getPaddingTop() + getPaddingBottom(); 343 | 344 | // 设置总尺寸 345 | setMeasuredDimension(width, nViewHeight); 346 | 347 | // 分割线初始化 348 | initDividerData(); 349 | } 350 | 351 | @Override 352 | protected void onLayout(boolean change, int l, int t, int r, int b) { 353 | mSlotView.layout(0, mSlotOffsetY, 354 | mSlotView.getMeasuredWidth(), mSlotOffsetY + mSlotView.getMeasuredHeight()); 355 | 356 | // 单元视图 357 | int count = getIconViewCount(); 358 | for (int i = 0; i < count; i++) { 359 | View childView = getIconView(i); 360 | AnimInfo animInfo = getViewHolder(childView).getAnimInfo(); 361 | layoutItem(childView, i, animInfo.isMove()); 362 | } 363 | } 364 | 365 | @Override 366 | protected void onDraw(Canvas canvas) { 367 | super.onDraw(canvas); 368 | 369 | // 分割线 370 | if (mIsDividerEnable) { 371 | drawDivider(canvas); 372 | } 373 | } 374 | 375 | /** 376 | * 初始化分割线数据 377 | */ 378 | public void initDividerData() { 379 | // 计算绘制行数 380 | int row = getIconViewCount() / mColCount; 381 | int col = getIconViewCount() % mColCount; 382 | mDividerRow = ((col == 0) ? row + 1 : row + 2); 383 | 384 | // 计算绘制列 385 | mDividerCol = mColCount + 1; 386 | } 387 | 388 | /** 389 | * 绘制分割线 390 | * 391 | * @param aCanvas 画布 392 | */ 393 | public void drawDivider(Canvas aCanvas) { 394 | // 绘制交叉线 395 | drawCrossLine(aCanvas, null, 0, getDividerWidth()); 396 | } 397 | 398 | /** 399 | * @return 分割线图片 400 | */ 401 | public Drawable getDivider() { 402 | /* if (BdThemeManager.getInstance().isNightT5()) { 403 | return mDividerNight; 404 | } else { 405 | return mDividerDay; 406 | }*/ 407 | 408 | return mDividerDay; 409 | } 410 | 411 | /** 412 | * 绘制分割线 413 | * 414 | * @param aCanvas 画布 415 | * @param aPaint 画笔 416 | * @param aLineOffset 偏移 417 | * @param aLineWidth 线宽度 418 | */ 419 | public void drawCrossLine(Canvas aCanvas, Paint aPaint, int aLineOffset, int aLineWidth) { 420 | // 变量 421 | int max; 422 | int offset; 423 | 424 | int lastCol = getIconViewCount() % mColCount; 425 | int bannerRow = getSlotRow(); 426 | Drawable divider = getDivider(); 427 | 428 | // Horizontal line 429 | max = mDividerRow; 430 | 431 | int left = getPaddingLeft(); 432 | int right = getMeasuredWidth() - getPaddingRight(); 433 | offset = getPaddingTop() + aLineOffset; 434 | 435 | for (int i = 0; i < max; i++) { 436 | if (i == max - 1) { // 最后一行停留在某个格子右边 437 | // 右边终点重新确定 438 | if (lastCol > 0) { 439 | right = (int) (getPaddingLeft() + lastCol * mCellWidth + (lastCol + 1) * getDividerWidth()); 440 | } 441 | } else if (i == bannerRow && mSlotView.getMeasuredHeight() > 0) { // banner特殊处理 442 | divider.setBounds(left, offset, right, offset + aLineWidth); 443 | divider.draw(aCanvas); 444 | 445 | offset += getDividerWidth() + mSlotView.getMeasuredHeight(); 446 | } 447 | // 绘制 448 | divider.setBounds(left, offset, right, offset + aLineWidth); 449 | divider.draw(aCanvas); 450 | 451 | offset += mCellHeight + getDividerWidth(); 452 | } 453 | 454 | // Vertical line 455 | max = mDividerCol; 456 | 457 | int top = getPaddingTop(); 458 | int bottom = 0; 459 | 460 | for (int i = 0; i < max; i++) { 461 | offset = (int) (getPaddingLeft() + aLineOffset + i * (mCellWidth + getDividerWidth())); 462 | if (i > lastCol && lastCol > 0) { 463 | bottom = (int) (getPaddingTop() + mCellHeight * (mRowCount - 1) + getDividerWidth() * mRowCount); 464 | } else { 465 | bottom = (int) (getPaddingTop() + mCellHeight * mRowCount + getDividerWidth() * (mRowCount + 1)); 466 | } 467 | if (bottom >= mSlotOffsetY && mSlotView.getMeasuredHeight() > 0) { 468 | int midBottom = mSlotOffsetY - getDividerWidth(); 469 | int midTop = mSlotOffsetY + mSlotView.getMeasuredHeight(); 470 | bottom += mSlotView.getMeasuredHeight(); 471 | 472 | divider.setBounds(offset, top, offset + aLineWidth, midBottom); 473 | divider.draw(aCanvas); 474 | 475 | divider.setBounds(offset, midTop, offset + aLineWidth, bottom); 476 | divider.draw(aCanvas); 477 | } else { 478 | divider.setBounds(offset, top, offset + aLineWidth, bottom); 479 | divider.draw(aCanvas); 480 | } 481 | } 482 | } 483 | 484 | /** 485 | * 增加数据项对应的子项 486 | * 487 | * @param aItemView item view 488 | * @param isAfterInit init 489 | */ 490 | private void addItemView(View aItemView, boolean isAfterInit) { 491 | if (isAfterInit) { 492 | addIconView(aItemView, getIconViewCount() - 1); 493 | } else { 494 | addIconView(aItemView); 495 | } 496 | } 497 | 498 | /** 499 | * 布局子项;可重载,允许子类有实现其它功能的机会 500 | * 501 | * @param aChild 子项 502 | * @param aPos 位置 503 | * @param aIsAnim 是否做动画 504 | */ 505 | public void layoutItem(View aChild, int aPos, boolean aIsAnim) { 506 | // 获取视图的动画信息 507 | ViewHolder holder = getViewHolder(aChild); 508 | AnimInfo animInfo = holder.getAnimInfo(); 509 | 510 | // 获取相应位置的矩形区域 511 | final Rect r = mAssistRect; 512 | getChildArea(r, aChild, aPos); 513 | 514 | // 如果动画进行中,重新定义动画属性; 否则直接布局 515 | if (aIsAnim) { 516 | animInfo.beginMove(aChild.getLeft(), aChild.getTop(), r.left, r.top); 517 | } else { 518 | aChild.layout(r.left, r.top, r.right, r.bottom); 519 | } 520 | 521 | // 重新定义视图位置 522 | holder.setPosition(aPos); 523 | } 524 | 525 | /** 526 | * 更新动画中子项的状态 527 | */ 528 | public void updateAnimInfo(float aFactor) { 529 | // 更新移动项 530 | int count = getIconViewCount(); 531 | for (int i = 0; i < count; i++) { 532 | View itemView = getIconView(i); 533 | AnimInfo animInfo = getViewHolder(itemView).getAnimInfo(); 534 | if (animInfo.isMove()) { 535 | animInfo.move(aFactor); 536 | } 537 | } 538 | } 539 | 540 | /** 541 | * 更新动画中子项的布局 542 | */ 543 | public void updateAnimLayout(float aFactor) { 544 | // 重新布局 545 | int count = getIconViewCount(); 546 | for (int i = 0; i < count; i++) { 547 | View itemView = getIconView(i); 548 | AnimInfo animInfo = getViewHolder(itemView).getAnimInfo(); 549 | if (animInfo.isMove()) { 550 | itemView.layout(animInfo.getX(), animInfo.getY(), 551 | animInfo.getX() + itemView.getMeasuredWidth(), 552 | animInfo.getY() + itemView.getMeasuredHeight()); 553 | 554 | // 结束标记 555 | if (aFactor == 1.0f) { 556 | animInfo.endMove(); 557 | } 558 | } 559 | } 560 | } 561 | 562 | /** 563 | * 获取给定位置上的子项区域 564 | * 565 | * @param outRect 存储区域 566 | * @param child 子项 567 | * @param pos 子项位置 568 | */ 569 | public void getChildArea(Rect outRect, View child, int pos) { 570 | getCellArea(outRect, pos); 571 | 572 | int offsetX = (int) (outRect.left + (mCellWidth - child.getMeasuredWidth()) / 2); 573 | int offsetY = (int) (outRect.top + (mCellHeight - child.getMeasuredHeight()) / 2); 574 | 575 | outRect.set(offsetX, offsetY, offsetX + child.getMeasuredWidth(), offsetY + child.getMeasuredHeight()); 576 | } 577 | 578 | /** 579 | * 获取单元格的区域 580 | * 581 | * @param outRect 所在区域 582 | * @param pos 单元格位置 583 | */ 584 | public void getCellArea(Rect outRect, int pos) { 585 | int row = pos / mColCount; 586 | int col = pos % mColCount; 587 | 588 | int bannerRow = (mRowCount > mSlotOffsetRow ? mSlotOffsetRow : mRowCount); 589 | int startX = (int) (getPaddingLeft() + (col + 1) * getDividerWidth() + col * mCellWidth); 590 | int startY = (int) (getPaddingTop() + (row + 1) * getDividerWidth() + row * mCellHeight); 591 | // 如果banner在宫格的上方存在,那么要多加一条分割线 592 | if ((row >= bannerRow) && mSlotView.getMeasuredHeight() > 0) { 593 | startY = startY + mSlotView.getMeasuredHeight() + getDividerWidth(); 594 | } 595 | outRect.set(startX, startY, (int) (startX + mCellWidth), (int) (startY + mCellHeight)); 596 | } 597 | 598 | /** 599 | * @return banner所在行 600 | */ 601 | public int getSlotRow() { 602 | return (mRowCount > mSlotOffsetRow ? mSlotOffsetRow : mRowCount); 603 | } 604 | 605 | /** 606 | * 快速定位位置 607 | * 608 | * @param x 当前坐标x 609 | * @param y 当前坐标y 610 | * @return 命中的单元格索引 611 | */ 612 | public int getCellPosition(int x, int y) { 613 | // 先去除banner的偏移 614 | if (y > mSlotOffsetY) { 615 | y -= mSlotView.getMeasuredHeight(); 616 | } 617 | 618 | int row = (int) ((y - getPaddingTop()) / mCellHeight); 619 | int col = (int) ((x - getPaddingLeft()) / mCellWidth); 620 | return row * mColCount + col; 621 | } 622 | 623 | /** 624 | * @return 单元格宽度 625 | */ 626 | public int getCellWidth() { 627 | return (int) mCellWidth; 628 | } 629 | 630 | /** 631 | * @return 单元格高度 632 | */ 633 | public int getCellHeight() { 634 | 635 | 636 | return mCellHeight == -1 ? getResources().getDimensionPixelSize(R.dimen.home_item_height): mCellHeight; 637 | } 638 | 639 | /** 640 | * @return 分割线宽度 641 | */ 642 | public int getDividerWidth() { 643 | return (mIsDividerEnable ? mDividerWidth : 0); 644 | } 645 | 646 | /** 647 | * @return 默认分割线宽度 648 | */ 649 | public int getDividerWidthDef() { 650 | return mDividerWidth == -1 ? getResources().getDimensionPixelOffset(R.dimen.home_divider_width): mDividerWidth; 651 | } 652 | 653 | 654 | 655 | 656 | /** 657 | * @return 总行数 658 | */ 659 | public int getRowCount() { 660 | return mRowCount; 661 | } 662 | 663 | /** 664 | * @return 总列数 665 | */ 666 | public int getColCount() { 667 | return mColCount == -1 ? DEF_COLCOUNT : mColCount; 668 | } 669 | 670 | /** 671 | * 改变子项的位置 672 | * 673 | * @param aFromPosition 原始位置 674 | * @param aToPosition 终点位置 675 | * @param isAnimation 是否附带动画效果 676 | */ 677 | public void changeItemPosition(int aFromPosition, int aToPosition, boolean isAnimation) { 678 | int nChildCount = getIconViewCount(); 679 | 680 | // 边界判断 681 | if ((aFromPosition < 0) || (aFromPosition >= nChildCount) || (aToPosition < 0) 682 | || (aToPosition >= nChildCount)) { 683 | return; 684 | } 685 | 686 | // 寻找子项 687 | View fromView = null; 688 | View toView = null; 689 | for (int i = 0; i < nChildCount; i++) { 690 | View childView = getIconView(i); 691 | if (getViewPosition(childView) == aFromPosition) { 692 | fromView = childView; 693 | } 694 | if (getViewPosition(childView) == aToPosition) { 695 | toView = childView; 696 | } 697 | } 698 | 699 | // 设置新的项 700 | if (fromView == toView) { 701 | layoutItem(fromView, aToPosition, isAnimation); 702 | } else { 703 | layoutItem(fromView, aToPosition, isAnimation); 704 | layoutItem(toView, aFromPosition, isAnimation); 705 | } 706 | } 707 | 708 | /** 709 | * @param aView 视图 710 | * @return 视图位置 711 | */ 712 | public int getViewPosition(View aView) { 713 | return getViewHolder(aView).getPosition(); 714 | } 715 | 716 | /** 717 | * @param aView 视图 718 | * @param aPos 视图位置 719 | */ 720 | public void setViewPosition(View aView, int aPos) { 721 | getViewHolder(aView).setPosition(aPos); 722 | } 723 | 724 | /** 725 | * @param aView 视图 726 | * @return holder 727 | */ 728 | private ViewHolder getViewHolder(View aView) { 729 | ViewHolder holder = (ViewHolder) aView.getTag(VIEW_HOLDER_TAG); 730 | if (holder == null) { 731 | holder = new ViewHolder(); 732 | aView.setTag(VIEW_HOLDER_TAG, holder); 733 | } 734 | return holder; 735 | } 736 | 737 | /** 738 | * 数据更新类 739 | */ 740 | class BdCellDataObserver extends DataSetObserver { 741 | @Override 742 | public void onChanged() { 743 | super.onChanged(); 744 | 745 | // 刷新视图 746 | refreshViews(); 747 | } 748 | } 749 | 750 | /** 751 | * 视图holder 752 | */ 753 | class ViewHolder { 754 | /** 755 | * 动画信息 756 | */ 757 | AnimInfo mAnimInfo; 758 | /** 759 | * 视图数据 760 | */ 761 | Object mViewData; 762 | /** 763 | * 视图位置 764 | */ 765 | int mViewPosition; 766 | 767 | /** 768 | * 构造函数 769 | */ 770 | public ViewHolder() { 771 | mAnimInfo = new AnimInfo(); 772 | } 773 | 774 | /** 775 | * @return 动画信息 776 | */ 777 | public AnimInfo getAnimInfo() { 778 | return mAnimInfo; 779 | } 780 | 781 | /** 782 | * @param aData 数据 783 | */ 784 | public void setData(Object aData) { 785 | mViewData = aData; 786 | } 787 | 788 | /** 789 | * @return 数据 790 | */ 791 | public Object getData() { 792 | return mViewData; 793 | } 794 | 795 | /** 796 | * @param aPosition 位置 797 | */ 798 | public void setPosition(int aPosition) { 799 | mViewPosition = aPosition; 800 | } 801 | 802 | /** 803 | * @return 位置 804 | */ 805 | public int getPosition() { 806 | return mViewPosition; 807 | } 808 | 809 | } 810 | 811 | /** 812 | * 动画信息 813 | */ 814 | class AnimInfo { 815 | 816 | /** 817 | * 目标坐标 818 | */ 819 | int mStartX; 820 | 821 | /** 822 | * 目标坐标 823 | */ 824 | int mStartY; 825 | 826 | /** 827 | * 目标坐标 828 | */ 829 | int mTargetX; 830 | 831 | /** 832 | * 目标坐标 833 | */ 834 | private int mTargetY; 835 | 836 | /** 837 | * 目标坐标 838 | */ 839 | private int mMoveX; 840 | 841 | /** 842 | * 目标坐标 843 | */ 844 | private int mMoveY; 845 | 846 | /** 847 | * 目标坐标 848 | */ 849 | private boolean mIsMove; 850 | 851 | /** 852 | * 开始移动 853 | * 854 | * @param aStartX 起始x值 855 | * @param aStartY 起始y值 856 | * @param aTargetX 目标x值 857 | * @param aTargetY 目标y值 858 | */ 859 | public void beginMove(int aStartX, int aStartY, int aTargetX, int aTargetY) { 860 | setIsMove(true); 861 | 862 | mTargetX = aTargetX; 863 | mTargetY = aTargetY; 864 | 865 | mStartX = aStartX; 866 | mStartY = aStartY; 867 | } 868 | 869 | /** 870 | * 结束移动 871 | */ 872 | public void endMove() { 873 | setIsMove(false); 874 | } 875 | 876 | /** 877 | * @param aFactor 比例 878 | */ 879 | public void move(float aFactor) { 880 | if (isMove()) { 881 | mMoveX = mStartX + (int) ((mTargetX - mStartX) * aFactor); 882 | mMoveY = mStartY + (int) ((mTargetY - mStartY) * aFactor); 883 | } 884 | } 885 | 886 | /** 887 | * 设置是否在移动 888 | * 889 | * @param isMove 标志 890 | */ 891 | public void setIsMove(boolean isMove) { 892 | mIsMove = isMove; 893 | } 894 | 895 | /** 896 | * 判断是否在移动 897 | * 898 | * @return 判断结果 899 | */ 900 | public boolean isMove() { 901 | return mIsMove; 902 | } 903 | 904 | /** 905 | * @return x 906 | */ 907 | public int getX() { 908 | return mMoveX; 909 | } 910 | 911 | /** 912 | * @return y 913 | */ 914 | public int getY() { 915 | return mMoveY; 916 | } 917 | 918 | } 919 | 920 | } 921 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PluginAdapter.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import com.squareup.picasso.Picasso; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | /** 12 | * PluginAdapter baseAdapter 13 | * Liuyongkui 14 | * */ 15 | public class PluginAdapter extends PaAbsAdapter { 16 | /** mContext. */ 17 | private Context mContext; 18 | /** PluginConfigModle datas. */ 19 | private List mModles = new ArrayList(); 20 | /** Loaders. */ 21 | private Picasso mImageLoader; 22 | 23 | 24 | /** 25 | * @param mContext 26 | * @param mModles 27 | */ 28 | public PluginAdapter(Context mContext, List mModles) { 29 | super(mContext, mModles); 30 | this.mContext = mContext; 31 | 32 | } 33 | 34 | 35 | /** 36 | * @param mContext 37 | * @param mImageLoader 38 | * @param mModles 39 | */ 40 | public PluginAdapter(Context mContext, Picasso mImageLoader, 41 | List mModles) { 42 | super(mContext, mModles); 43 | this.mContext = mContext; 44 | this.mModles = mModles; 45 | this.mImageLoader = mImageLoader; 46 | } 47 | 48 | public void setData(List aDatas) { 49 | mModles = aDatas; 50 | } 51 | 52 | @Override 53 | public int getCount() { 54 | 55 | return mModles == null ? 0 : mModles.size(); 56 | } 57 | 58 | @Override 59 | public PluginConfigModle getItem(int position) { 60 | 61 | return mModles == null ? null : mModles.get(position); 62 | } 63 | 64 | @Override 65 | public long getItemId(int position) { 66 | 67 | return mModles == null ? null : Long.parseLong(mModles.get(position).getID()); 68 | } 69 | 70 | @Override 71 | public View getView(int position, View convertView, ViewGroup parent) { 72 | 73 | if (mModles != null && mModles.size() != 0) { 74 | PluginGridViewItem itemView = new PluginGridViewItem( 75 | mContext, mModles.get(position), mImageLoader); 76 | convertView = itemView; 77 | } 78 | return convertView; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PluginConfigModle.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import com.tamic.linegridview.base.BaseBean; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * 插件配置模型 12 | * Created by LIUYONGKUI726 on 2016-01-28. 13 | */ 14 | public class PluginConfigModle extends BaseBean{ 15 | 16 | 17 | /*插件ID*/ 18 | private String ID; 19 | /*插件类型*/ 20 | private int type; 21 | /*插件名*/ 22 | private String pluginName; 23 | /*描述*/ 24 | private String description; 25 | /*包名*/ 26 | private String packageName; 27 | /*版本号*/ 28 | private int version; 29 | /*主界面*/ 30 | private String mainActivity; 31 | /*是否为独立插件*/ 32 | private String isEnabled; 33 | /*插件图标*/ 34 | private String appIcon; 35 | /*插件下载地址*/ 36 | private String downUrl; 37 | 38 | 39 | /** 40 | * Construrtor 41 | */ 42 | public PluginConfigModle() { 43 | } 44 | 45 | 46 | /** 47 | * @param ID 48 | * @param type 49 | * @param pluginName 50 | * @param packageName 51 | * @param description 52 | * @param version 53 | * @param mainActivity 54 | * @param isEnabled 55 | * @param appIcon 56 | * @param downUrl 57 | */ 58 | public PluginConfigModle(String ID, int type, String pluginName, 59 | String packageName, String description, int version, 60 | String mainActivity, String isEnabled, String appIcon, 61 | String downUrl) { 62 | this.ID = ID; 63 | this.type = type; 64 | this.pluginName = pluginName; 65 | this.packageName = packageName; 66 | this.description = description; 67 | this.version = version; 68 | this.mainActivity = mainActivity; 69 | this.isEnabled = isEnabled; 70 | this.appIcon = appIcon; 71 | this.downUrl = downUrl; 72 | } 73 | 74 | 75 | 76 | protected PluginConfigModle(Parcel in) { 77 | ID = in.readString(); 78 | type = in.readInt(); 79 | pluginName = in.readString(); 80 | description = in.readString(); 81 | packageName = in.readString(); 82 | version = in.readInt(); 83 | mainActivity = in.readString(); 84 | isEnabled = in.readString(); 85 | appIcon = in.readString(); 86 | downUrl = in.readString(); 87 | } 88 | 89 | /* public static final Creator CREATOR = new Creator() { 90 | @Override 91 | public PluginConfigModle createFromParcel(Parcel in) { 92 | return new PluginConfigModle(in); 93 | } 94 | 95 | @Override 96 | public PluginConfigModle[] newArray(int size) { 97 | return new PluginConfigModle[size]; 98 | } 99 | };*/ 100 | 101 | public String getID() { 102 | return ID; 103 | } 104 | 105 | public void setID(String ID) { 106 | this.ID = ID; 107 | } 108 | 109 | public String getPackageName() { 110 | return packageName; 111 | } 112 | 113 | public void setPackageName(String packageName) { 114 | this.packageName = packageName; 115 | } 116 | 117 | public int getVersion() { 118 | return version; 119 | } 120 | 121 | public void setVersion(int version) { 122 | this.version = version; 123 | } 124 | 125 | public String getMainActivity() { 126 | return mainActivity; 127 | } 128 | 129 | public void setMainActivity(String mainActivity) { 130 | this.mainActivity = mainActivity; 131 | } 132 | 133 | public String getIsEnabled() { 134 | return isEnabled; 135 | } 136 | 137 | public void setIsEnabled(String isEnabled) { 138 | this.isEnabled = isEnabled; 139 | } 140 | 141 | public String getAppIcon() { 142 | return appIcon; 143 | } 144 | 145 | public void setAppIcon(String appIcon) { 146 | this.appIcon = appIcon; 147 | } 148 | 149 | public String getDownUrl() { 150 | return downUrl; 151 | } 152 | 153 | public void setDownUrl(String downUrl) { 154 | this.downUrl = downUrl; 155 | } 156 | 157 | public String getDescription() { 158 | return description; 159 | } 160 | 161 | public void setDescription(String description) { 162 | this.description = description; 163 | } 164 | 165 | public String getPluginName() { 166 | return pluginName; 167 | } 168 | 169 | public void setPluginName(String pluginName) { 170 | this.pluginName = pluginName; 171 | } 172 | 173 | public int getType() { 174 | return type; 175 | } 176 | 177 | public void setType(int type) { 178 | this.type = type; 179 | } 180 | 181 | /* @Override 182 | public int describeContents() { 183 | return 0; 184 | } 185 | 186 | @Override 187 | public void writeToParcel(Parcel dest, int flags) { 188 | dest.writeString(ID); 189 | dest.writeInt(type); 190 | dest.writeString(pluginName); 191 | dest.writeString(description); 192 | dest.writeString(packageName); 193 | dest.writeInt(version); 194 | dest.writeString(mainActivity); 195 | dest.writeString(isEnabled); 196 | dest.writeString(appIcon); 197 | dest.writeString(downUrl); 198 | }*/ 199 | 200 | @Override 201 | public String toString() { 202 | return "PluginConfigModle{" + 203 | "ID='" + ID + '\'' + 204 | ", type=" + type + 205 | ", pluginName='" + pluginName + '\'' + 206 | ", description='" + description + '\'' + 207 | ", packageName='" + packageName + '\'' + 208 | ", version=" + version + 209 | ", mainActivity='" + mainActivity + '\'' + 210 | ", isEnabled='" + isEnabled + '\'' + 211 | ", appIcon='" + appIcon + '\'' + 212 | ", downUrl='" + downUrl + '\'' + 213 | '}'; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PluginGridView.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.content.Intent; 7 | import android.graphics.Bitmap; 8 | import android.graphics.BitmapFactory; 9 | import android.graphics.Canvas; 10 | import android.graphics.Paint; 11 | import android.graphics.Paint.Style; 12 | import android.text.TextUtils; 13 | import android.util.AttributeSet; 14 | import android.util.Log; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | /** 22 | * pligin icon GridView. 23 | * 24 | * @author liuyongkui 25 | * 26 | */ 27 | public class PluginGridView extends BaseGridView implements PluginGridViewItem.OnItemClickListener{ 28 | 29 | /** 默认列数. */ 30 | public static final int DEFAULT_COLUMN = 3; 31 | 32 | /** 33 | * 行数 34 | */ 35 | public int mRowCount; 36 | /** 列数. */ 37 | public static int mColCount = DEFAULT_COLUMN; 38 | /** 39 | * 列数 40 | *//* 41 | private int mColCount = DEFAULT_COLUMN;*/ 42 | 43 | /** 横屏默认列数. */ 44 | public static final int HSPAND_DEFAULT_COLUMN = 4; 45 | 46 | /** 分割线颜色. */ 47 | public static final int UI_CROSSLINE_COLOR = 0x1a000000; 48 | 49 | /** 分割线夜间颜色. */ 50 | public static final int UI_CROSSLINE_COLOR_NIGHT = 0x19000000; 51 | 52 | /** 竖屏时左右 Padding间距 */ 53 | public static final float PADDING_PORTRAIT = 20f; 54 | 55 | /** 竖屏时ICON间距 */ 56 | public static final float ICON_SPACING_PORTRAIT = 80f; 57 | 58 | /** 横屏时左右padding */ 59 | public static float PADDING_LANDSCAPE = 200f; 60 | 61 | /** 横屏时ICON间距 */ 62 | public static float ICON_SPACING_LANDSCAPE = 120f; 63 | 64 | /** TOP. */ 65 | private static int PENDING_TOP = 0; 66 | 67 | /** BUTTOM. */ 68 | private static int PENDING_BUTTOM = 0; 69 | 70 | /** 透明度. */ 71 | public static final int ALPHA_HALF = 128; 72 | 73 | /** 透明度(无). */ 74 | public static final int ALPHA_NO = 255; 75 | /** 竖分割线. */ 76 | private static Bitmap mDivider; 77 | 78 | /** 竖分割线夜间. */ 79 | private static Bitmap mDividerNight; 80 | 81 | /** 横分割线画笔. */ 82 | private Paint mPaint; 83 | 84 | /** 竖线画笔. */ 85 | private Paint mPaint1; 86 | 87 | /** 行和行之间的间隔,列和列之间的间隔. */ 88 | private int mSpacing; 89 | /** 是否需要分割线. */ 90 | private boolean mIsNeedDivider; 91 | 92 | /** 屏幕密度. */ 93 | private float mDensity; 94 | 95 | /** child view height. */ 96 | private int mChildHeight; 97 | 98 | /** child view widht. */ 99 | private int mChildWidth; 100 | 101 | /** data source. */ 102 | private PluginAdapter mAdapter; 103 | 104 | /** child views. */ 105 | private List mChildViews; 106 | 107 | /** 字条目. */ private int childCount; 108 | 109 | /** 弹出安装对话框. *//* 110 | private BdPopupDialog mInstallDialog;*/ 111 | 112 | /** Tag. */ 113 | 114 | private String TAG = "PluginGridView"; 115 | 116 | /** divider line color */ 117 | public static final int UI_DIVIDER_LINE_COLOR = 0x14000000; 118 | 119 | /** divider line color night */ 120 | public static final int UI_DIVIDER_LINE_COLOR_NIGHT = 0x0affffff; 121 | 122 | /** 视图左右Padding */ 123 | private int mPadding; 124 | 125 | private String mkey; 126 | 127 | 128 | /** 129 | * constructor. 130 | * 131 | * @param context 132 | * context 133 | * @param aAdapter 134 | * data source 135 | * */ 136 | public PluginGridView(Context context, PluginAdapter aAdapter) { 137 | super(context, aAdapter); 138 | mAdapter = aAdapter; 139 | init(); 140 | } 141 | 142 | /** 143 | * constructor. 144 | * 145 | * @param context 146 | * context 147 | * @param attrs 148 | * AttributeSet 149 | * *//* 150 | public PluginGridView(Context context, AttributeSet attrs) { 151 | super(context, attrs); 152 | } 153 | 154 | *//** 155 | * constructor. 156 | * 157 | * @param context 158 | * context 159 | * @param attrs 160 | * AttributeSet 161 | * @param defStyle 162 | * int 163 | * */ 164 | /*public PluginGridView(Context context, AttributeSet attrs, int defStyle) { 165 | super(context, attrs, defStyle); 166 | }*/ 167 | 168 | /** 169 | * init. 170 | * */ 171 | private void init() { 172 | mDensity = getResources().getDisplayMetrics().density; 173 | mPaint = new Paint(); 174 | mPaint.setStyle(Style.STROKE); 175 | mPaint.setStrokeWidth(1); 176 | mPaint.setColor(UI_CROSSLINE_COLOR); 177 | mPaint1 = new Paint(); 178 | 179 | setWillNotDraw(false); 180 | 181 | mChildViews = new ArrayList(); 182 | for (int i = 0; i < mAdapter.getCount(); i++) { 183 | PluginGridViewItem childView = (PluginGridViewItem) mAdapter 184 | .getView(i, null, null); 185 | childView.setId(i); 186 | childView.setOnItemClickListener(PluginGridView.this); 187 | childView.setOnClickListener(PluginGridView.this); 188 | childView.setOnLongClickListener(PluginGridView.this); 189 | mChildViews.add(childView); 190 | addView(childView); 191 | } 192 | } 193 | 194 | /** 195 | * refresh grid view. 196 | * */ 197 | public void refresh() { 198 | removeAllViews(); 199 | init(); 200 | this.requestLayout(); 201 | this.postInvalidate(); 202 | } 203 | 204 | /** 205 | * 设置列数,默认为5. 206 | * 207 | * @param aCol 208 | * col to be set 209 | * */ 210 | public void setColumn(int aCol) { 211 | mColCount = aCol; 212 | } 213 | 214 | /** 215 | * 设置行高. 216 | * 217 | * @param aItemHeight 218 | * item height to be set 219 | * */ 220 | public void setItemHeight(int aItemHeight) { 221 | mChildHeight = aItemHeight; 222 | } 223 | 224 | /** 225 | * set is need to draw divider. 226 | * 227 | * @param aIsNeed 228 | * value to be set 229 | * */ 230 | public void setIsNeedDivider(boolean aIsNeed) { 231 | mIsNeedDivider = aIsNeed; 232 | } 233 | 234 | /** 235 | * get divider bitmap. 236 | * 237 | * @return bitmap 238 | * */ 239 | private Bitmap getDividerBitmap() { 240 | if (mDivider == null) { 241 | 242 | 243 | mDivider = BitmapFactory.decodeResource(getResources(), R.drawable.home_navi_divider); 244 | 245 | /* mDivider = PaResource.getImage(getContext(), 246 | R.drawable.home_navi_divider);*/ 247 | 248 | } 249 | return mDivider; 250 | } 251 | 252 | /** 253 | * get divider bitmap night. 254 | * 255 | * @return bitmap 256 | * */ 257 | private Bitmap getDividerBitmapNight() { 258 | if (mDividerNight == null) { 259 | mDividerNight =BitmapFactory.decodeResource(getResources(), R.drawable.home_navi_divider_night); 260 | /* PaResource.getImage(getContext(), 261 | R.drawable.home_navi_divider_night);*/ 262 | } 263 | return mDividerNight; 264 | } 265 | 266 | @Override 267 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 268 | 269 | int width = MeasureSpec.getSize(widthMeasureSpec); 270 | int height = 0; 271 | 272 | childCount = mChildViews.size(); 273 | 274 | // 计算总行数和总列数 275 | int row = childCount / mColCount; 276 | int col = childCount % mColCount; 277 | mRowCount = ((col == 0) ? row : row + 1); 278 | 279 | int screenWidth = getResources().getDisplayMetrics().widthPixels; 280 | int screenHeight = getResources().getDisplayMetrics().heightPixels; 281 | if (screenWidth > screenHeight) { 282 | int temp = screenWidth; 283 | screenWidth = screenHeight; 284 | screenHeight = temp; 285 | } 286 | 287 | if (ViewUtils.isLandscape(getContext())) { 288 | mColCount = HSPAND_DEFAULT_COLUMN; 289 | mPadding = (int) (PADDING_LANDSCAPE * screenHeight / 1280)/2; 290 | mSpacing = (int) ((ICON_SPACING_LANDSCAPE - PADDING_LANDSCAPE) 291 | * screenHeight / 1280); 292 | mChildWidth = (width - (mColCount - 1) * mSpacing - 2 * mPadding) 293 | / mColCount; 294 | } else { 295 | mColCount = DEFAULT_COLUMN; 296 | mPadding = (int) (PADDING_PORTRAIT * screenWidth / 720) / 2; 297 | mSpacing = 0; 298 | mChildWidth = (width - mPadding*2) / mColCount; 299 | } 300 | 301 | //childCount = mAdapter.getCount(); 302 | /*if (mChildViews.size() < mColCount) { 303 | childCount = mChildViews.size(); 304 | }*//*else{ 305 | childCount = mColCount; 306 | }*/ 307 | 308 | if (mChildViews.size() > 0) { 309 | for (int i = 0; i < childCount; i++) { 310 | if (mChildHeight == 0) { 311 | mChildHeight = getChildAt(i).getMeasuredHeight(); 312 | } 313 | mChildViews.get(i).measure( 314 | MeasureSpec.makeMeasureSpec(mChildWidth, 315 | MeasureSpec.EXACTLY), 316 | MeasureSpec.makeMeasureSpec(mChildHeight, 317 | MeasureSpec.UNSPECIFIED)); 318 | } 319 | height = Math.round(mRowCount * mChildHeight + (mRowCount -1) * getDividerBitmap().getWidth()); 320 | setMeasuredDimension(width, height); 321 | } else { 322 | setMeasuredDimension(0, 0); 323 | } 324 | } 325 | 326 | @Override 327 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 328 | int offsetX = 0; 329 | int offsetY = 0; 330 | View childeView; 331 | for (int i = 0; i < childCount; i++) { 332 | int row = i / mColCount; 333 | int loc=i % mColCount; 334 | 335 | offsetX = mPadding + (mSpacing + mChildWidth)*loc; 336 | offsetY = PENDING_TOP + (mSpacing + mChildHeight)*row; 337 | childeView = mChildViews.get(i); 338 | childeView.layout(offsetX, offsetY, 339 | offsetX + childeView.getMeasuredWidth(), 340 | offsetY + childeView.getMeasuredHeight()); 341 | } 342 | } 343 | 344 | @Override 345 | protected void onDraw(Canvas canvas) { 346 | 347 | int width = getWidth(); 348 | int height = getHeight(); 349 | 350 | if (!mIsNeedDivider) { 351 | return; 352 | } 353 | try { 354 | 355 | if (childCount <= 0) { 356 | return; 357 | } 358 | setLinePaint(); 359 | Bitmap drawable = null; 360 | drawable = getDividerBitmap(); 361 | View childView = getChildAt(0); 362 | int childWidth = childView.getMeasuredWidth(); 363 | int childHeight = childView.getMeasuredHeight(); 364 | if (drawable == null) { 365 | int offsetY = (childHeight - drawable.getHeight()) >> 1; 366 | for (int i = 0; i < childCount; i++) { 367 | // 划竖线 368 | int rowIndex = i / mColCount; 369 | int colIndex = i % mColCount; 370 | /*int offsetX = mPadding + (mSpacing + childWidth)*colIndex ; 371 | * offsetY + rowIndex *(childHeight + mSpacing)*/ 372 | int offsetX = (colIndex + 1) * childWidth 373 | + colIndex * mSpacing + mPadding; 374 | offsetY = PENDING_TOP + (mSpacing + childHeight)* rowIndex; 375 | if ((colIndex + 1) % (mColCount) != 0) { 376 | 377 | canvas.drawBitmap(drawable, offsetX, offsetY, mPaint1); 378 | } 379 | } 380 | } else { 381 | int offsetY = childHeight; 382 | 383 | for (int i = 0; i < childCount; i++) { 384 | // 划竖线 385 | int rowIndex = i / mColCount; 386 | int colIndex = i % mColCount; 387 | int offsetX = (colIndex + 1) * childWidth 388 | + colIndex * mSpacing + mPadding; 389 | offsetY = (mSpacing + childHeight)* rowIndex; 390 | 391 | if ((colIndex + 1) % (mColCount) != 0) { 392 | canvas.drawLine(offsetX, offsetY, offsetX, 393 | offsetY + mChildHeight, 394 | mPaint); 395 | } 396 | } 397 | } 398 | // 划横线 399 | int rowNum = childCount / mColCount; 400 | if (childCount % mColCount != 0) { 401 | rowNum++; 402 | } 403 | for (int j = 0; j < rowNum - 1; j++) { 404 | canvas.drawLine( 405 | mSpacing, 406 | (j + 1) * (childHeight) + j * (mSpacing + PENDING_TOP), 407 | mColCount * (mSpacing + childWidth), 408 | (j + 1) * (childHeight) + j * (mSpacing + PENDING_TOP), 409 | mPaint); 410 | } 411 | 412 | if (mPaint == null) { 413 | mPaint = new Paint(); 414 | } 415 | mPaint.setColor(UI_DIVIDER_LINE_COLOR); 416 | mPaint.setStrokeWidth(1.0f); 417 | canvas.drawLine(0, height-1, width, height - 1, mPaint); 418 | } catch (Exception e) { 419 | e.printStackTrace(); // 增加异常捕获 420 | } 421 | super.onDraw(canvas); 422 | } 423 | 424 | public static int getPENDING_TOP() { 425 | return PENDING_TOP; 426 | } 427 | 428 | public static void setPENDING_TOP(int pENDING_TOP) { 429 | PENDING_TOP = pENDING_TOP; 430 | } 431 | 432 | public static int getPENDING_BUTTOM() { 433 | return PENDING_BUTTOM; 434 | } 435 | 436 | public static void setPENDING_BUTTOM(int pENDING_BUTTOM) { 437 | PENDING_BUTTOM = pENDING_BUTTOM; 438 | } 439 | 440 | /** 441 | * 设置夜间模式. 442 | * */ 443 | private void setLinePaint() { 444 | /*if (BdThemeManager.getInstance().isNightT5()) { 445 | mPaint.setColor(UI_CROSSLINE_COLOR_NIGHT); 446 | mPaint1.setAlpha(ALPHA_NO); 447 | } else { 448 | mPaint.setColor(UI_CROSSLINE_COLOR); 449 | mPaint1.setAlpha(ALPHA_NO); 450 | }*/ 451 | 452 | mPaint.setColor(UI_CROSSLINE_COLOR); 453 | mPaint1.setAlpha(ALPHA_NO); 454 | } 455 | 456 | @Override 457 | public void onClick(PluginGridViewItem v, PluginConfigModle model) { 458 | 459 | } 460 | 461 | @Override 462 | public void onPressDown(PluginGridViewItem v) { 463 | 464 | v.setBackground(); 465 | 466 | } 467 | 468 | @Override 469 | public void onPressUp(PluginGridViewItem v) { 470 | 471 | v.setBackground(); 472 | 473 | } 474 | 475 | 476 | 477 | 478 | @Override 479 | public void onClick(View v) { 480 | Log.d(TAG, "onclick"); 481 | if (!(v instanceof PluginGridViewItem)) { 482 | return; 483 | } 484 | ((PluginGridViewItem)v).setBackground(); 485 | } 486 | 487 | /* 488 | @Override 489 | public boolean onLongClick(View v) { 490 | 491 | PluginConfigModle ConfigModle = ((PluginGridViewItem) v).getPluginModle(); 492 | 493 | 494 | 495 | return true; 496 | }*/ 497 | 498 | @Override 499 | public void onItemClick(View v) { 500 | 501 | } 502 | 503 | @Override 504 | public boolean onItemLongClick(View v) { 505 | return false; 506 | } 507 | } 508 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PluginGridViewItem.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.graphics.Bitmap; 6 | import android.graphics.drawable.Drawable; 7 | import android.net.Uri; 8 | import android.util.AttributeSet; 9 | import android.util.TypedValue; 10 | import android.view.Gravity; 11 | import android.view.MotionEvent; 12 | import android.widget.ImageView; 13 | import android.widget.RelativeLayout; 14 | import android.widget.TextView; 15 | 16 | import com.squareup.picasso.Picasso; 17 | 18 | 19 | /* 20 | * Class info:GridViewItem 21 | * Created by:liuyongkui. 22 | */ 23 | public class PluginGridViewItem extends RelativeLayout { 24 | 25 | /** 完全不透明度 */ 26 | private static final int FULL_ALPHA = 255; 27 | 28 | /** 半不透明度 */ 29 | private static final int HALF_ALPHA = 128; 30 | 31 | /** icon名称文字的大小,单位dp */ 32 | private static final int SUG_NAME_TEXT_SIZE = 12; 33 | 34 | /** ICON 视图的ID */ 35 | private static final int SUG_ICON_ID = 0x0101; 36 | 37 | /** 数据 */ 38 | private PluginConfigModle mGuideModle; 39 | 40 | /** ICON */ 41 | private ImageView mSugIcon; 42 | 43 | /** 名称 */ 44 | private TextView mSugName; 45 | 46 | /** 上下文 */ 47 | private Context mContext; 48 | 49 | /** 图片加载器 */ 50 | private Picasso mImageLoader; 51 | 52 | /** 该视图宽度 */ 53 | private int mWidth; 54 | 55 | /** 该视图高度 */ 56 | private int mHeight; 57 | 58 | /** ICON 的宽高 */ 59 | private int mIconWidth; 60 | 61 | /** SUG 名称视图的高度 */ 62 | private int mTextHeight; 63 | 64 | /** SUG 名称视图的宽度 */ 65 | private int mTextWidth; 66 | 67 | /** 是否按下 */ 68 | private boolean mIsPressed; 69 | 70 | /** 按下时的背景 */ 71 | private Drawable mCellPressDrawable; 72 | 73 | /** 夜间模式下按下时的背景 */ 74 | private Drawable mNightCellPressDrawable; 75 | 76 | /** 77 | * 默认图片,使用static减少对象数 78 | */ 79 | private static Bitmap mDefaultIcon; 80 | 81 | /** 点击事件监听器 */ 82 | private OnItemClickListener mItemClickListener; 83 | 84 | private PluginGridViewItem(Context aContext, AttributeSet aAttrs) { 85 | super(aContext, aAttrs); 86 | } 87 | 88 | private PluginGridViewItem(Context aContext) { 89 | this(aContext, null); 90 | } 91 | 92 | public PluginGridViewItem(Context aContext, 93 | PluginConfigModle aGuideModle, Picasso aImageLoader) { 94 | this(aContext); 95 | mGuideModle = aGuideModle; 96 | mContext = aContext; 97 | mImageLoader = aImageLoader; 98 | init(); 99 | } 100 | 101 | public PluginConfigModle getPluginModle() { 102 | return mGuideModle; 103 | } 104 | 105 | public void setPluginModle(PluginConfigModle mGuideModle) { 106 | this.mGuideModle = mGuideModle; 107 | } 108 | 109 | /*** 110 | * 检查屏幕的方向. 111 | * 112 | * @return false 113 | */ 114 | private boolean isLandscape() { 115 | if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 116 | return true; 117 | } else { 118 | return false; 119 | } 120 | } 121 | 122 | /** 123 | * 计算ICON的宽度,以及该视图的宽高 124 | */ 125 | private void initCellWidth() { 126 | int screenHeight = mContext.getResources().getDisplayMetrics().heightPixels; 127 | int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels; 128 | 129 | if (screenWidth > screenHeight) { 130 | int temp = screenWidth; 131 | screenWidth = screenHeight; 132 | screenHeight = temp; 133 | } 134 | 135 | if (isLandscape()) { 136 | 137 | int m = PluginGridView.mColCount; 138 | int n = m - 1; 139 | 140 | int padding = (int) (PluginGridView.PADDING_LANDSCAPE * screenHeight / 1280); 141 | int spacing = (int) (PluginGridView.ICON_SPACING_LANDSCAPE 142 | * screenHeight / 1280); 143 | mIconWidth = (screenHeight - n * spacing - 2 * padding) / m ; 144 | 145 | spacing = (int) ((PluginGridView.ICON_SPACING_LANDSCAPE - PluginGridView.PADDING_LANDSCAPE) 146 | * screenHeight / 1280); 147 | mWidth = (screenHeight - n * spacing - padding) / m; 148 | 149 | } else { 150 | 151 | int m = PluginGridView.mColCount; 152 | int n = m - 1; 153 | int padding = (int) (PluginGridView.PADDING_PORTRAIT * screenWidth / 720); 154 | int spacing = (int) (PluginGridView.ICON_SPACING_PORTRAIT 155 | * screenWidth / 720); 156 | mIconWidth = (screenWidth - n * spacing - 2 * padding) / m; 157 | 158 | padding = (int) (PluginGridView.PADDING_PORTRAIT * screenWidth / 720) / 2; 159 | spacing = 0; 160 | mWidth = (screenWidth - padding * 2) / m; 161 | } 162 | } 163 | 164 | /** 165 | * 初始化视图 166 | */ 167 | private void init() { 168 | 169 | mCellPressDrawable = getResources().getDrawable( 170 | R.drawable.home_item_bg); 171 | 172 | mNightCellPressDrawable = getResources().getDrawable( 173 | R.drawable.home_item_night_bg); 174 | 175 | /* mDefaultIcon = BitmapFactory.decodeResource(getResources(), 176 | R.drawable.sug_default_icon);*/ 177 | 178 | /* // init the icon view 179 | initCellWidth(); 180 | /*mSugIcon = new BdImageView(mContext); 181 | mSugIcon.setImageBitmap(mDefaultIcon); 182 | //mSugIcon.setId(SUG_ICON_ID); 183 | mSugIcon.setScaleType(ScaleType.FIT_XY); 184 | mSugIcon.setRadius(mContext.getResources().getDimensionPixelSize( 185 | R.dimen.sug_icon_corner_radius)); 186 | mSugIcon.setUrl(mGuideModle.getAppIcon(), true);*/ 187 | 188 | mSugIcon = new ImageView(mContext); 189 | //mSugIcon.setImageBitmap(mDefaultIcon); 190 | //mSugIcon.setId(SUG_ICON_ID); 191 | mSugIcon.setScaleType(ImageView.ScaleType.FIT_XY); 192 | mSugIcon.setMaxHeight(mWidth); 193 | mSugIcon.setMaxWidth(mWidth); 194 | 195 | mImageLoader.load(mGuideModle.getAppIcon()).into(mSugIcon); 196 | 197 | LayoutParams params = new LayoutParams( 198 | mWidth, mWidth); 199 | params.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE); 200 | params.topMargin = mContext.getResources().getDimensionPixelSize( 201 | R.dimen.sug_item_icon_top_margin); 202 | this.addView(mSugIcon, params); 203 | 204 | // init the name view 205 | mSugName = new TextView(mContext); 206 | mSugName.setMaxLines(1); 207 | mSugName.setText(mGuideModle.getPluginName()); 208 | mSugName.setTextSize(TypedValue.COMPLEX_UNIT_SP, SUG_NAME_TEXT_SIZE); 209 | mSugName.setGravity(Gravity.CENTER); 210 | mSugName.setTextColor(mContext.getResources().getColor( 211 | R.color.sug_item_name_color)); 212 | LayoutParams txtParams = new LayoutParams( 213 | LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); 214 | txtParams.topMargin = mContext.getResources().getDimensionPixelSize( 215 | R.dimen.sug_item_text_top_margin); 216 | txtParams.bottomMargin = mContext.getResources().getDimensionPixelSize( 217 | R.dimen.sug_item_text_bottom_margin); 218 | txtParams.addRule(RelativeLayout.BELOW, SUG_ICON_ID); 219 | txtParams 220 | .addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE); 221 | mSugName.setLayoutParams(txtParams); 222 | this.addView(mSugName); 223 | 224 | mTextHeight = (int) (mSugName.getPaint().getFontMetrics().descent - mSugName 225 | .getPaint().getFontMetrics().top); 226 | mTextWidth = (int) mSugName.getPaint().measureText( 227 | mGuideModle.getPluginName()); 228 | 229 | //onThemeChanged(0); 230 | } 231 | 232 | /** 233 | * 设置点击事件监听器 234 | * 235 | * @param aClickListener 236 | * 点击事件监听器 237 | */ 238 | public void setOnItemClickListener(OnItemClickListener aClickListener) { 239 | mItemClickListener = aClickListener; 240 | } 241 | 242 | @Override 243 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 244 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 245 | initCellWidth(); 246 | 247 | mHeight = mIconWidth 248 | + mContext.getResources().getDimensionPixelSize( 249 | R.dimen.sug_item_icon_top_margin) 250 | + mContext.getResources().getDimensionPixelSize( 251 | R.dimen.sug_item_text_top_margin) 252 | + mTextHeight 253 | + mContext.getResources().getDimensionPixelSize( 254 | R.dimen.sug_item_text_bottom_margin); 255 | 256 | setMeasuredDimension(mWidth, mHeight); 257 | } 258 | 259 | @Override 260 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 261 | if (mSugIcon != null) { 262 | mSugIcon.layout( 263 | (mWidth - mIconWidth) / 2, 264 | mContext.getResources().getDimensionPixelSize( 265 | R.dimen.sug_item_icon_top_margin), 266 | (mWidth + mIconWidth) / 2, 267 | mContext.getResources().getDimensionPixelSize( 268 | R.dimen.sug_item_icon_top_margin) 269 | + mIconWidth); 270 | } 271 | 272 | if (mSugName != null) { 273 | int top = mContext.getResources().getDimensionPixelSize( 274 | R.dimen.sug_item_icon_top_margin) 275 | + mIconWidth 276 | + mContext.getResources().getDimensionPixelSize( 277 | R.dimen.sug_item_text_top_margin); 278 | int bottom = mHeight 279 | - mContext.getResources().getDimensionPixelSize( 280 | R.dimen.sug_item_text_bottom_margin); 281 | 282 | if (mTextWidth > mWidth) { 283 | mSugName.layout(0, top, mWidth, bottom); 284 | } else { 285 | mSugName.layout((mWidth - mTextWidth) / 2, top, 286 | (mWidth + mTextWidth) / 2, bottom); 287 | } 288 | 289 | } 290 | } 291 | 292 | /** 293 | * 处理手势. 294 | * 295 | * @see android.view.View#onTouchEvent(MotionEvent) 296 | */ 297 | @Override 298 | public boolean onTouchEvent(MotionEvent event) { 299 | switch (event.getAction()) { 300 | case MotionEvent.ACTION_DOWN: 301 | 302 | mIsPressed = true; 303 | if (mItemClickListener != null) { 304 | mItemClickListener.onPressDown(PluginGridViewItem.this); 305 | } 306 | break; 307 | 308 | case MotionEvent.ACTION_UP: 309 | mIsPressed = false; 310 | if (mItemClickListener != null) { 311 | mItemClickListener.onClick(PluginGridViewItem.this, 312 | mGuideModle); 313 | } 314 | break; 315 | 316 | case MotionEvent.ACTION_CANCEL: 317 | mIsPressed = false; 318 | if (mItemClickListener != null) { 319 | mItemClickListener.onPressUp(PluginGridViewItem.this); 320 | } 321 | break; 322 | 323 | default: 324 | break; 325 | } 326 | 327 | return super.onTouchEvent(event); 328 | } 329 | 330 | /** 331 | * Item点击监听. 332 | */ 333 | public interface OnItemClickListener { 334 | 335 | /** 336 | * 点击. 337 | */ 338 | void onClick(PluginGridViewItem v, PluginConfigModle model); 339 | 340 | 341 | /** 342 | * 按下. 343 | */ 344 | void onPressDown(PluginGridViewItem v); 345 | 346 | /** 347 | * 弹起. 348 | */ 349 | void onPressUp(PluginGridViewItem v); 350 | } 351 | 352 | 353 | public void setBackground() { 354 | if (mIsPressed) { 355 | setBackgroundDrawable(mCellPressDrawable); 356 | } else { 357 | setBackgroundDrawable(null); 358 | } 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/PluginGridview2.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by liuyongkui on 2016-09-02. 8 | */ 9 | public class PluginGridview2 extends BaseGridView { 10 | 11 | 12 | 13 | public PluginGridview2(Context context, PaAbsAdapter adapter, int aCount) { 14 | super(context, adapter, aCount); 15 | } 16 | 17 | public PluginGridview2(Context context, PaAbsAdapter adapter) { 18 | super(context, adapter); 19 | } 20 | 21 | @Override 22 | public void onItemClick(View v) { 23 | 24 | } 25 | 26 | @Override 27 | public boolean onItemLongClick(View v) { 28 | return false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/ViewUtils.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Filename: BdViewHelper.java 3 | * Description: 4 | * Copyright: Baidu MIC Copyright(c)2013 5 | * @author: Rambow 6 | * @version: 1.0 7 | * Create at: May 22, 2013 1:50:58 PM 8 | * 9 | * Modification History: 10 | * Date Author Version Description 11 | * ------------------------------------------------------------------ 12 | * May 22, 2013 Rambow 1.0 1.0 Version 13 | */ 14 | package com.tamic.linegridview; 15 | 16 | import android.app.Activity; 17 | import android.content.Context; 18 | import android.content.res.Configuration; 19 | import android.graphics.Bitmap; 20 | import android.graphics.Rect; 21 | import android.util.DisplayMetrics; 22 | import android.view.View; 23 | import android.view.ViewGroup; 24 | 25 | /** 26 | * View的工具类 27 | */ 28 | public final class ViewUtils { 29 | /** 默认状态栏的高度, dip */ 30 | public static final int DEFAULT_STATUSBAR_HEIGHT = 24; 31 | 32 | /** 缓存图片 */ 33 | private static Bitmap sCache = null; 34 | 35 | /** 36 | * Constructor 37 | */ 38 | private ViewUtils() { 39 | 40 | } 41 | 42 | /** 43 | * 强制对View及其子视图进行递归刷新 44 | * 45 | * @param aView 46 | * 需要重绘的View(也有可能是ViewGroup) 47 | */ 48 | public static void forceInvalidateView(View aView) { 49 | if (aView instanceof ViewGroup) { 50 | ViewGroup childGroup = (ViewGroup) aView; 51 | int childCnt = childGroup.getChildCount(); 52 | for (int i = 0; i < childCnt; i++) { 53 | View childView = childGroup.getChildAt(i); 54 | forceInvalidateView(childView); 55 | } 56 | } 57 | if (aView != null) { 58 | invalidate(aView); 59 | } 60 | } 61 | 62 | /** 63 | * 获得status bar的高度 64 | * 65 | * @param aActivity 66 | * activity 67 | * @return status bar高度 68 | */ 69 | public static int getStatusbarHeight(Activity aActivity) { 70 | int statusbarHeight; 71 | try { 72 | Rect frame = new Rect(); 73 | aActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); 74 | statusbarHeight = frame.top; 75 | } catch (Exception e) { 76 | final DisplayMetrics dm = aActivity.getResources().getDisplayMetrics(); 77 | statusbarHeight = (int) (DEFAULT_STATUSBAR_HEIGHT * dm.density); 78 | } 79 | return statusbarHeight; 80 | } 81 | 82 | /** 83 | * 从parent中移出指定child 84 | * 85 | * @param aChild 86 | * child 87 | */ 88 | public static void removeFromParent(View aChild) { 89 | if (aChild != null) { 90 | View parent = (View) aChild.getParent(); 91 | if (parent != null && parent instanceof ViewGroup) { 92 | ((ViewGroup) parent).removeView(aChild); 93 | } 94 | } 95 | } 96 | 97 | /** 98 | * layout指定的view 99 | * @param aView view 100 | */ 101 | public static void requestLayout(View aView) { 102 | if (aView != null) { 103 | aView.requestLayout(); 104 | } 105 | } 106 | 107 | /** 108 | * 强行递归layout 109 | * @param aView 根View 110 | */ 111 | public static void requestLayoutAllRecurse(View aView) { 112 | if (aView != null && aView instanceof ViewGroup) { 113 | int cnt = ((ViewGroup) aView).getChildCount(); 114 | for (int i = 0; i < cnt; i++) { 115 | View child = ((ViewGroup) aView).getChildAt(i); 116 | if (child != null && child instanceof ViewGroup) { 117 | requestLayoutAllRecurse(child); 118 | } else if (child != null) { 119 | child.requestLayout(); 120 | } 121 | 122 | } 123 | } 124 | } 125 | 126 | /** 127 | * 把invalidate换成这个方法,是为了便于增加打印堆栈,方便找出哪里触发了界面更新 128 | * @param aView view 129 | */ 130 | public static void invalidate(View aView) { 131 | if (aView != null) { 132 | aView.invalidate(); 133 | } 134 | } 135 | 136 | /** 137 | * 把postInvalidate换成这个方法 138 | * @param aView view 139 | */ 140 | public static void postInvalidate(View aView) { 141 | if (aView != null) { 142 | aView.postInvalidate(); 143 | } 144 | } 145 | 146 | /** 147 | * 强制对View及其子视图进行递归刷新 148 | * 149 | * @param aView view 150 | */ 151 | public static void forceChildrenInvalidateRecursively(View aView) { 152 | if (aView instanceof ViewGroup) { 153 | ViewGroup childGroup = (ViewGroup) aView; 154 | int childCnt = childGroup.getChildCount(); 155 | for (int i = 0; i < childCnt; i++) { 156 | View childView = childGroup.getChildAt(i); 157 | forceChildrenInvalidateRecursively(childView); 158 | } 159 | } 160 | if (aView != null) { 161 | invalidate(aView); 162 | } 163 | } 164 | 165 | /** 166 | * 当前是否是横屏 167 | * 168 | * @param aContext 169 | * context 170 | * @return true表示是横屏 171 | */ 172 | public static boolean isLandscape(Context aContext) { 173 | //因为小说会强制竖屏,所以这个判断不能添加前半句 174 | return (aContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE); 175 | } 176 | 177 | /** 178 | * 得到屏幕的高度 179 | * 180 | * @param aContext 181 | * context 182 | * @return screen height 183 | */ 184 | public static int getScreenHeight(Context aContext) { 185 | DisplayMetrics dm = aContext.getResources().getDisplayMetrics(); 186 | int screenHeight; 187 | if (isLandscape(aContext)) { 188 | screenHeight = Math.min(dm.widthPixels, dm.heightPixels); 189 | } else { 190 | screenHeight = Math.max(dm.widthPixels, dm.heightPixels); 191 | } 192 | return screenHeight; 193 | } 194 | 195 | /** 196 | * dip to pix 197 | * 198 | * @param aValue 199 | * dip 200 | * @param aDensity 201 | * density 202 | * @return pix 203 | */ 204 | public static int dip2pix(float aValue, float aDensity) { 205 | return Math.round(aValue * aDensity); 206 | } 207 | 208 | /** 209 | * dip to pix 210 | * 211 | * @param aValue 212 | * dip 213 | * @return pix 214 | /* *//* 215 | public static int dip2pix(Context context, float aValue) { 216 | return Math.round(aValue *context.getResources().getDisplayMetrics()); 217 | }*/ 218 | 219 | /** 220 | * pix to dip 221 | * 222 | * @param pix 223 | * pix 224 | * @return dip 225 | *//* 226 | public static int pix2pix(float pix) { 227 | return dip2pix(pix / 1.5f); //SUPPRESS CHECKSTYLE 228 | } 229 | */ 230 | /** 231 | * pix to dip 232 | * 233 | * @param aValue 234 | * pix 235 | * @param aDensity 236 | * density 237 | * @return dip 238 | */ 239 | public static int pix2dip(float aValue, float aDensity) { 240 | return Math.round(aValue / aDensity); 241 | } 242 | 243 | /** 244 | * pix to dip 245 | * 246 | * @param aValue 247 | * pix 248 | * @return dip 249 | */ 250 | public static float pix2dip(float aValue) { 251 | return Math.round(aValue / 1.5); //SUPPRESS CHECKSTYLE 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/base/BaseBean.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview.base; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by LIUYONGKUI726 on 2016-06-08. 7 | */ 8 | public abstract class BaseBean implements Serializable{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/base/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview.base; 2 | 3 | 4 | /** 5 | * 网络返回基类 支持泛型 6 | * Created by Tamic on 2016-06-06. 7 | */ 8 | public class BaseResponse extends BaseBean { 9 | 10 | /** 11 | * code : 0 12 | * msg : success 13 | * data : {} 14 | */ 15 | 16 | private int code; 17 | private String msg; 18 | private T data; 19 | 20 | 21 | public int getCode() { 22 | return code; 23 | } 24 | 25 | public void setCode(int code) { 26 | this.code = code; 27 | } 28 | 29 | public String getMsg() { 30 | return msg; 31 | } 32 | 33 | public void setMsg(String msg) { 34 | this.msg = msg; 35 | } 36 | 37 | public T getData() { 38 | return data; 39 | } 40 | 41 | public void setData(T data) { 42 | this.data = data; 43 | } 44 | 45 | public boolean isOk() { 46 | return code == 0; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/model/PluginData.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview.model; 2 | 3 | import com.tamic.linegridview.PluginConfigModle; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by LIUYONGKUI726 on 2016-02-02. 10 | */ 11 | public class PluginData implements Serializable { 12 | 13 | public int count; 14 | 15 | public List list; 16 | 17 | public List getList() { 18 | return list; 19 | } 20 | 21 | public void setList(List list) { 22 | this.list = list; 23 | } 24 | 25 | public int getCount() { 26 | return count; 27 | } 28 | 29 | public void setCount(int count) { 30 | this.count = count; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/java/com/tamic/linegridview/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview.util; 2 | 3 | import android.util.Log; 4 | 5 | import com.alibaba.fastjson.JSON; 6 | import com.alibaba.fastjson.TypeReference; 7 | import com.alibaba.fastjson.parser.Feature; 8 | 9 | import java.lang.reflect.Type; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by liuyongkui726 on 2016-09-02. 14 | */ 15 | public class JsonUtil { 16 | 17 | /** 18 | * 解析实体 19 | * @param jsonStr 20 | * json字符串 21 | * @param entityClass 22 | * 实体类型 23 | * @param 24 | * 实体对象 25 | * @return 26 | */ 27 | public static T parseObject(String jsonStr, Class entityClass) { 28 | T ret = null; 29 | 30 | try { 31 | ret = JSON.parseObject(jsonStr, entityClass); 32 | } catch (Exception e) { 33 | Log.e("will", "parseObject-something Exception with:" + e.toString()); 34 | e.printStackTrace(); 35 | } 36 | 37 | return ret; 38 | } 39 | 40 | public static T parseObject(String jsonStr, Type type) { 41 | T obj = null; 42 | try { 43 | obj = JSON.parseObject(jsonStr, type, Feature.AutoCloseSource); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | return obj; 48 | } 49 | 50 | 51 | /** 解析成map 52 | * @param jsonStr 53 | * @param tf 54 | * @param 55 | * @return 56 | */ 57 | public static T parseObject(String jsonStr, TypeReference tf) { 58 | T obj = null; 59 | try { 60 | obj = JSON.parseObject(jsonStr, tf, Feature.AutoCloseSource); 61 | } catch (Exception e) { 62 | e.printStackTrace(); 63 | } 64 | return obj; 65 | } 66 | 67 | 68 | 69 | 70 | 71 | /** 72 | * 解析List 73 | * @param jsonStr 74 | * @param entityClass 75 | * @param 76 | * @return 77 | */ 78 | public static List parseList(String jsonStr, Class entityClass) { 79 | List ret = null; 80 | 81 | try { 82 | ret = JSON.parseArray(jsonStr, entityClass); 83 | } catch (Exception e) { 84 | e.printStackTrace(); 85 | } 86 | 87 | return ret; 88 | } 89 | 90 | public static String toJSONString(Object obj) { 91 | String ret = null; 92 | 93 | try { 94 | ret = JSON.toJSONString(obj); 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | } 98 | 99 | return ret; 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_divider_day.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_divider_night.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_item_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_item_night_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_navi_divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/drawable/home_navi_divider.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/drawable/home_navi_divider_night.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/drawable/home_navi_divider_night.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tamicer/LineGridView/42468531477d8a0eb7f69ef912f6971bdd356844/lineGridView/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | 8 | - 9 | #ffdcdcdc 10 | #ff24262c 11 | 12 | 13 | 14 | #494949 15 | #ff777777 16 | #14000000 17 | 18 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 1px 6 | 0dip 7 | 95dip 8 | 2dip 9 | 155dip 10 | 11 | 12 | 7dp 13 | 10dp 14 | 10dp 15 | 12sp 16 | 22.5dp 17 | 8dp 18 | 19 | 120dip 20 | 21 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | lineGridView 3 | 4 | -------------------------------------------------------------------------------- /lineGridView/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lineGridView/app/src/test/java/com/tamic/linegridview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.tamic.linegridview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /lineGridView/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | 6 | jcenter() 7 | } 8 | dependencies { 9 | //classpath 'com.android.tools.build:gradle:2.1.0' 10 | classpath 'com.android.tools.build:gradle:1.5.0' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | 20 | jcenter() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | -------------------------------------------------------------------------------- /lineGridView/gradle.properties: -------------------------------------------------------------------------------- 1 | ## Project-wide Gradle settings. 2 | # 3 | # For more details on how to configure your build environment visit 4 | # http://www.gradle.org/docs/current/userguide/build_environment.html 5 | # 6 | # Specifies the JVM arguments used for the daemon process. 7 | # The setting is particularly useful for tweaking memory settings. 8 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 10 | # 11 | # When configured, Gradle will run in incubating parallel mode. 12 | # This option should only be used with decoupled projects. More details, visit 13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 14 | # org.gradle.parallel=true 15 | #Fri Sep 02 11:31:59 CST 2016 16 | systemProp.http.proxyHost=10.59.72.13 17 | systemProp.http.proxyPort=3128 18 | -------------------------------------------------------------------------------- /lineGridView/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /lineGridView/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /lineGridView/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------