├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lzy │ │ └── hexagonviewdemo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lzy │ │ │ └── hexagonviewdemo │ │ │ └── HexagonActivity.java │ └── res │ │ ├── layout │ │ └── activity_hexagon.xml │ │ ├── mipmap-hdpi │ │ ├── hexagon_image.jpg │ │ └── ic_launcher.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lzy │ └── hexagonviewdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── hexagonview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── widget │ │ └── HexagonView.java │ └── res │ └── values │ └── attrs.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | /local.properties 5 | /screenshots 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HexagonView 2 | 六边形带圆角的自定义View,支持图文混排,点击区域,水平垂直方向切换,圆角大小等各种属性 3 | 4 | ### 联系方式 5 | * 邮箱地址: liaojeason@126.com 6 | * QQ群: 489873144 (建议使用QQ群,邮箱使用较少,可能看的不及时) 7 | * 本群刚建立,旨在为使用我的github项目的人提供方便,如果遇到问题欢迎在群里提问。个人能力也有限,希望一起学习一起进步。 8 | 9 | 10 | ## 演示 11 | ![image](http://7xss53.com2.z0.glb.clouddn.com/hexagonview/demo0.png)![image](http://7xss53.com2.z0.glb.clouddn.com/hexagonview/demo2.gif)![image](http://7xss53.com2.z0.glb.clouddn.com/hexagonview/demo1.gif) 12 | 13 | ## 1.用法 14 | 15 | 该项目和我github上其他的view相关的项目已经一起打包上传到jCenter仓库中(源码地址 [https://github.com/jeasonlzy0216/ViewCore](https://github.com/jeasonlzy0216/ViewCore) ),使用的时候可以直接使用compile依赖,用法如下 16 | ```java 17 | compile 'com.lzy.widget:view-core:0.1.9' 18 | ``` 19 | 或者使用 20 | ```java 21 | compile project(':hexagonview') 22 | ``` 23 | 24 | ## 2.注意 25 | 由于该控件不是矩形,所以想要点击事件只在六边形区域有效,需要设置`OnHexagonViewClickListener`,代码如下: 26 | ```java 27 | hexagon.setOnHexagonClickListener(new HexagonView.OnHexagonViewClickListener() { 28 | @Override 29 | public void onClick(View view) { 30 | Toast.makeText(HexagonActivity.this, "点击六边形了!", Toast.LENGTH_SHORT).show(); 31 | } 32 | }); 33 | ``` 34 | 35 | ## 3.参数含义 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
自定义属性名字参数含义
hexagonText文字内容
hexagonTextSize文字大小
hexagonTextColor文字颜色
hexagonBorderWidtd边框宽度
hexagonBorderColor边框颜色
hexagonFillColor背景填充色
hexagonCorner圆角大小
hexagonBreakLineCount换行字节数,一个中文代表两个字节
hexagonMaxLine允许的最大行数,超过显示...
hexagonTextSpacing每行文本的间距
hexagonBorderOverlay边框是否覆盖在背景之上
hexagonOrientation六边的的方向,横向和
95 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /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.lzy.hexagonviewdemo" 9 | minSdkVersion 8 10 | targetSdkVersion 22 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(include: ['*.jar'], dir: 'libs') 24 | compile 'com.android.support:appcompat-v7:23.1.1' 25 | 26 | // compile 'com.lzy.widget:view-core:0.1.9' 27 | compile 'com.lzy.utils:colorpicker:0.1.0' 28 | compile project(':hexagonview') 29 | } 30 | -------------------------------------------------------------------------------- /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 E:\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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lzy/hexagonviewdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.lzy.hexagonviewdemo; 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 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lzy/hexagonviewdemo/HexagonActivity.java: -------------------------------------------------------------------------------- 1 | package com.lzy.hexagonviewdemo; 2 | 3 | import android.content.Intent; 4 | import android.database.Cursor; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.net.Uri; 8 | import android.os.Bundle; 9 | import android.provider.MediaStore; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.text.Editable; 12 | import android.text.TextWatcher; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.Button; 16 | import android.widget.CheckBox; 17 | import android.widget.CompoundButton; 18 | import android.widget.EditText; 19 | import android.widget.RadioGroup; 20 | import android.widget.SeekBar; 21 | import android.widget.TextView; 22 | import android.widget.Toast; 23 | 24 | import com.lzy.colorpicker.ColorPickerDialog; 25 | import com.lzy.widget.HexagonView; 26 | 27 | public class HexagonActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, RadioGroup.OnCheckedChangeListener, CompoundButton.OnCheckedChangeListener, TextWatcher, View.OnClickListener { 28 | 29 | private static final int SELECT_PIC_KITKAT = 0; 30 | private static final int SELECT_PIC = 1; 31 | private TextView tv_textSize; 32 | private TextView tv_borderWidth; 33 | private TextView tv_corner; 34 | private TextView tv_breakLineCount; 35 | private TextView tv_maxLine; 36 | private TextView tv_textSpacing; 37 | private TextView tv_width; 38 | private TextView tv_height; 39 | private TextView tv_padding; 40 | private HexagonView hexagon; 41 | ViewGroup.LayoutParams params; 42 | 43 | private int textColor = 0xFFFFFFFF; 44 | private int borderColor = 0x99FFFF00; 45 | private int fillColor = 0xFFFF0000; 46 | private int backColor = 0x00000000; 47 | 48 | @Override 49 | protected void onCreate(Bundle savedInstanceState) { 50 | super.onCreate(savedInstanceState); 51 | setContentView(R.layout.activity_hexagon); 52 | 53 | hexagon = (HexagonView) findViewById(R.id.hexagon); 54 | 55 | tv_textSize = (TextView) findViewById(R.id.tv_textSize); 56 | tv_borderWidth = (TextView) findViewById(R.id.tv_borderWidth); 57 | tv_corner = (TextView) findViewById(R.id.tv_corner); 58 | tv_breakLineCount = (TextView) findViewById(R.id.tv_breakLineCount); 59 | tv_maxLine = (TextView) findViewById(R.id.tv_maxLine); 60 | tv_textSpacing = (TextView) findViewById(R.id.tv_textSpacing); 61 | tv_width = (TextView) findViewById(R.id.tv_width); 62 | tv_height = (TextView) findViewById(R.id.tv_height); 63 | tv_padding = (TextView) findViewById(R.id.tv_padding); 64 | 65 | SeekBar sb_textSize = (SeekBar) findViewById(R.id.sb_textSize); 66 | sb_textSize.setOnSeekBarChangeListener(this); 67 | sb_textSize.setMax(50); 68 | sb_textSize.setProgress(20); 69 | SeekBar sb_borderWidth = (SeekBar) findViewById(R.id.sb_borderWidth); 70 | sb_borderWidth.setOnSeekBarChangeListener(this); 71 | sb_borderWidth.setMax(50); 72 | sb_borderWidth.setProgress(20); 73 | SeekBar sb_corner = (SeekBar) findViewById(R.id.sb_corner); 74 | sb_corner.setOnSeekBarChangeListener(this); 75 | sb_corner.setMax(50); 76 | sb_corner.setProgress(10); 77 | SeekBar sb_breakLineCount = (SeekBar) findViewById(R.id.sb_breakLineCount); 78 | sb_breakLineCount.setOnSeekBarChangeListener(this); 79 | sb_breakLineCount.setMax(15); 80 | sb_breakLineCount.setProgress(6); 81 | SeekBar sb_maxLine = (SeekBar) findViewById(R.id.sb_maxLine); 82 | sb_maxLine.setOnSeekBarChangeListener(this); 83 | sb_maxLine.setMax(5); 84 | sb_maxLine.setProgress(3); 85 | SeekBar sb_textSpacing = (SeekBar) findViewById(R.id.sb_textSpacing); 86 | sb_textSpacing.setOnSeekBarChangeListener(this); 87 | sb_textSpacing.setMax(20); 88 | sb_textSpacing.setProgress(0); 89 | SeekBar sb_width = (SeekBar) findViewById(R.id.sb_width); 90 | sb_width.setOnSeekBarChangeListener(this); 91 | sb_width.setMax(300); 92 | sb_width.setProgress(200); 93 | SeekBar sb_height = (SeekBar) findViewById(R.id.sb_height); 94 | sb_height.setOnSeekBarChangeListener(this); 95 | sb_height.setMax(300); 96 | sb_height.setProgress(200); 97 | SeekBar sb_padding = (SeekBar) findViewById(R.id.sb_padding); 98 | sb_padding.setOnSeekBarChangeListener(this); 99 | sb_padding.setMax(100); 100 | sb_padding.setProgress(10); 101 | 102 | RadioGroup orientation = (RadioGroup) findViewById(R.id.orientation); 103 | orientation.setOnCheckedChangeListener(this); 104 | orientation.check(R.id.vertical); 105 | 106 | CheckBox borderOverlay = (CheckBox) findViewById(R.id.borderOverlay); 107 | borderOverlay.setOnCheckedChangeListener(this); 108 | borderOverlay.setChecked(false); 109 | CheckBox isUseBitmap = (CheckBox) findViewById(R.id.isUseBitmap); 110 | isUseBitmap.setOnCheckedChangeListener(this); 111 | isUseBitmap.setChecked(true); 112 | CheckBox enableClick = (CheckBox) findViewById(R.id.enableClick); 113 | enableClick.setOnCheckedChangeListener(this); 114 | enableClick.setChecked(true); 115 | 116 | Button checkImage = (Button) findViewById(R.id.checkImage); 117 | checkImage.setOnClickListener(this); 118 | Button textColor = (Button) findViewById(R.id.textColor); 119 | textColor.setOnClickListener(this); 120 | Button borderColor = (Button) findViewById(R.id.borderColor); 121 | borderColor.setOnClickListener(this); 122 | Button fillColor = (Button) findViewById(R.id.fillColor); 123 | fillColor.setOnClickListener(this); 124 | Button backColor = (Button) findViewById(R.id.backColor); 125 | backColor.setOnClickListener(this); 126 | 127 | EditText text = (EditText) findViewById(R.id.text); 128 | text.addTextChangedListener(this); 129 | text.setText("ABC这是EFG测试文字H"); 130 | text.selectAll(); 131 | } 132 | 133 | @Override 134 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 135 | switch (seekBar.getId()) { 136 | case R.id.sb_textSize: 137 | hexagon.setTextSize(progress); 138 | tv_textSize.setText(progress + "sp"); 139 | break; 140 | case R.id.sb_borderWidth: 141 | hexagon.setBorderWidth((int) (progress * getResources().getDisplayMetrics().density)); 142 | tv_borderWidth.setText(progress + "dp"); 143 | break; 144 | case R.id.sb_corner: 145 | hexagon.setCorner((int) (progress * getResources().getDisplayMetrics().density)); 146 | tv_corner.setText(progress + "dp"); 147 | break; 148 | case R.id.sb_breakLineCount: 149 | hexagon.setBreakLineCount(progress); 150 | tv_breakLineCount.setText(progress + ""); 151 | break; 152 | case R.id.sb_maxLine: 153 | hexagon.setMaxLine(progress); 154 | tv_maxLine.setText(progress + ""); 155 | break; 156 | case R.id.sb_textSpacing: 157 | hexagon.setTextSpacing((int) (progress * getResources().getDisplayMetrics().density)); 158 | tv_textSpacing.setText(progress + "dp"); 159 | break; 160 | case R.id.sb_width: 161 | params = hexagon.getLayoutParams(); 162 | params.width = (int) (progress * getResources().getDisplayMetrics().density); 163 | hexagon.setLayoutParams(params); 164 | tv_width.setText(progress + "dp"); 165 | break; 166 | case R.id.sb_height: 167 | params = hexagon.getLayoutParams(); 168 | params.height = (int) (progress * getResources().getDisplayMetrics().density); 169 | hexagon.setLayoutParams(params); 170 | tv_height.setText(progress + "dp"); 171 | break; 172 | case R.id.sb_padding: 173 | int padding = (int) (progress * getResources().getDisplayMetrics().density); 174 | hexagon.setPadding(padding, padding, padding, padding); 175 | tv_padding.setText(progress + "dp"); 176 | break; 177 | } 178 | } 179 | 180 | @Override 181 | public void onStartTrackingTouch(SeekBar seekBar) { 182 | 183 | } 184 | 185 | @Override 186 | public void onStopTrackingTouch(SeekBar seekBar) { 187 | 188 | } 189 | 190 | @Override 191 | public void onCheckedChanged(RadioGroup group, int checkedId) { 192 | switch (checkedId) { 193 | case R.id.horizontal: 194 | hexagon.setHexagonOrientation(HexagonView.HORIZONTAL); 195 | break; 196 | case R.id.vertical: 197 | hexagon.setHexagonOrientation(HexagonView.VERTICAL); 198 | break; 199 | } 200 | } 201 | 202 | @Override 203 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 204 | switch (buttonView.getId()) { 205 | case R.id.borderOverlay: 206 | hexagon.setBorderOverlay(isChecked); 207 | break; 208 | case R.id.isUseBitmap: 209 | if (isChecked) { 210 | hexagon.setImageResource(R.mipmap.hexagon_image); 211 | } else { 212 | hexagon.setImageBitmap(null); 213 | } 214 | break; 215 | case R.id.enableClick: 216 | if (isChecked) { 217 | hexagon.setOnHexagonClickListener(new HexagonView.OnHexagonViewClickListener() { 218 | @Override 219 | public void onClick(View view) { 220 | Toast.makeText(HexagonActivity.this, "点击六边形了!", Toast.LENGTH_SHORT).show(); 221 | } 222 | }); 223 | } else { 224 | hexagon.setOnHexagonClickListener(null); 225 | } 226 | } 227 | } 228 | 229 | @Override 230 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 231 | 232 | } 233 | 234 | @Override 235 | public void onTextChanged(CharSequence s, int start, int before, int count) { 236 | hexagon.setText(s.toString()); 237 | } 238 | 239 | @Override 240 | public void afterTextChanged(Editable s) { 241 | 242 | } 243 | 244 | @Override 245 | public void onClick(View v) { 246 | switch (v.getId()) { 247 | case R.id.textColor: 248 | ColorPickerDialog textDialog = new ColorPickerDialog(this, textColor); 249 | textDialog.setAlphaSliderVisible(true); 250 | textDialog.setHexValueEnabled(true); 251 | textDialog.show(); 252 | textDialog.setOnColorChangedListener(new ColorPickerDialog.OnColorChangedListener() { 253 | @Override 254 | public void onColorChanged(int color) { 255 | textColor = color; 256 | hexagon.setTextColor(color); 257 | } 258 | }); 259 | break; 260 | case R.id.borderColor: 261 | ColorPickerDialog borderDialog = new ColorPickerDialog(this, borderColor); 262 | borderDialog.setAlphaSliderVisible(true); 263 | borderDialog.setHexValueEnabled(true); 264 | borderDialog.show(); 265 | borderDialog.setOnColorChangedListener(new ColorPickerDialog.OnColorChangedListener() { 266 | @Override 267 | public void onColorChanged(int color) { 268 | borderColor = color; 269 | hexagon.setBorderColor(color); 270 | } 271 | }); 272 | break; 273 | case R.id.fillColor: 274 | ColorPickerDialog fillColorDialog = new ColorPickerDialog(this, fillColor); 275 | fillColorDialog.setAlphaSliderVisible(true); 276 | fillColorDialog.setHexValueEnabled(true); 277 | fillColorDialog.show(); 278 | fillColorDialog.setOnColorChangedListener(new ColorPickerDialog.OnColorChangedListener() { 279 | @Override 280 | public void onColorChanged(int color) { 281 | fillColor = color; 282 | hexagon.setFillColor(color); 283 | } 284 | }); 285 | break; 286 | case R.id.backColor: 287 | ColorPickerDialog backColorDialog = new ColorPickerDialog(this, backColor); 288 | backColorDialog.setAlphaSliderVisible(true); 289 | backColorDialog.setHexValueEnabled(true); 290 | backColorDialog.show(); 291 | backColorDialog.setOnColorChangedListener(new ColorPickerDialog.OnColorChangedListener() { 292 | @Override 293 | public void onColorChanged(int color) { 294 | backColor = color; 295 | hexagon.setBackgroundColor(color); 296 | } 297 | }); 298 | break; 299 | case R.id.checkImage: 300 | Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 301 | startActivityForResult(intent, 101); 302 | break; 303 | } 304 | } 305 | 306 | @Override 307 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 308 | super.onActivityResult(requestCode, resultCode, data); 309 | if (null != data && requestCode == 101) { 310 | Uri selectedImage = data.getData(); // content://media/external/images/media/16753 311 | String path = selectedImage.getPath(); // /external/images/media/16753 312 | String[] filePathColumn = {MediaStore.Images.Media.DATA}; 313 | Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); 314 | System.out.println("cursor:" + cursor); 315 | if (cursor != null) { 316 | cursor.moveToFirst(); 317 | int columnIndex = cursor.getColumnIndex(filePathColumn[0]); 318 | String picturePath = cursor.getString(columnIndex); // /storage/emulated/0/DCIM/Camera/1450292407465.jpg 319 | cursor.close(); 320 | Bitmap bitmap = BitmapFactory.decodeFile(picturePath); 321 | hexagon.setImageBitmap(bitmap); 322 | } 323 | } 324 | } 325 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_hexagon.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 23 | 24 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 40 | 41 | 44 | 45 | 50 | 51 | 52 | 53 | 54 | 57 | 58 | 61 | 62 | 67 | 68 | 69 | 70 | 71 | 74 | 75 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | 91 | 92 | 95 | 96 | 101 | 102 | 103 | 104 | 105 | 108 | 109 | 112 | 113 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 130 | 131 | 136 | 137 | 142 | 143 | 150 | 151 | 158 | 159 | 160 | 161 | 166 | 167 | 174 | 175 | 182 | 183 | 190 | 191 | 192 | 196 | 197 | 203 | 204 | 224 | 225 | 226 | 231 | 232 |