flutter版的文件管理器

第一次寫(xiě)文章够委,作為自己學(xué)習(xí)flutter過(guò)程中做一些記錄吧

最近在項(xiàng)目的過(guò)程中涉及到要訪問(wèn)內(nèi)存卡荐类,并且打開(kāi)文件的情況。調(diào)用原生的文件管理器效果不太理想茁帽,所以想著用flutter自定義一個(gè)玉罐。好了,開(kāi)始吧潘拨!

創(chuàng)建一個(gè)flutter項(xiàng)目開(kāi)始寫(xiě)代碼吊输。

要訪問(wèn)SD卡,首先讀取權(quán)限肯定是要有的铁追,不然寫(xiě)再多代碼都是無(wú)用功季蚂。
在AndroidManifest.xml文件中添加
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

新建一個(gè)dart文件file_manager.dart
這里需要使用到一個(gè)插件path_provider用來(lái)獲取SD卡根路徑(不嫌麻煩自己寫(xiě)原生也可以),在pubspec.yaml文件里添加相關(guān)依賴(lài)即可path_provider: ^0.4.1琅束。

然后在初始化函數(shù)使用String sDCardDir = (await getExternalStorageDirectory()).path;獲得SD卡的根路徑(一定要在初始化函數(shù)中就調(diào)用扭屁,不然運(yùn)行之后連個(gè)路徑都沒(méi)),從這個(gè)路徑就可以找出SD卡的所有文件和文件夾涩禀。
拿到這個(gè)路徑后使用directory.listSync()會(huì)自動(dòng)找出當(dāng)前目錄下所有文件和文件夾

List<FileSystemEntity> files = [];

var directory = Directory(sDCardDir);
files = directory.listSync();

把SD卡根目錄下的所有文件疯搅、文件夾都存放到files中,這也是這個(gè)文件管理器最核心的方法埋泵,傳入根目錄路徑就能找出根路徑下的所有文件和文件夾,那把其中一個(gè)文件夾的路徑再傳進(jìn)去(點(diǎn)擊一個(gè)文件夾的時(shí)候罪治,傳遞該文件夾路徑)丽声,就能找出這個(gè)文件夾里的所有文件和文件夾啦~

頁(yè)面顯示的時(shí)候使用了ListView布局,因?yàn)槲募?shù)量不確定觉义,也可能會(huì)很大雁社,所以使用了ListView.builder進(jìn)行構(gòu)建。具體代碼如下:

ListView.builder(
  controller: controller,
  itemCount: files.length,
  itemBuilder: (BuildContext context, int index) {
    return buildListViewItem(files[index]);
  },
),

返回的buildListViewItem就是具體的布局晒骇,簡(jiǎn)單使用ListTile就可以完成比較好看的顯示效果了霉撵。代碼還是貼上來(lái):

Column(
        children: <Widget>[
          ListTile(
            leading: Image.asset(selectIcon(isFile, file)),
            title: Row(
              children: <Widget>[
                Expanded(child: Text(file.path.substring(file.parent.path.length + 1))),
                isFile
                    ? Container()
                    : Text(
                        '$length項(xiàng)',
                        style: TextStyle(color: Colors.grey),
                      )
              ],
            ),
            subtitle: isFile
                ? Text(
                    '${getFileLastModifiedTime(file)}  ${getFileSize(file)}',
                    style: TextStyle(fontSize: 12.0),
                  )
                : null,
            trailing: isFile ? null : Icon(Icons.chevron_right),
          ),
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 14.0),
            child: Divider(
              height: 1.0,
            ),
          )
        ],
      ),

那如何判斷這是一個(gè)文件還是文件夾呢磺浙?這里有一個(gè)方法
var isFile = FileSystemEntity.isFileSync(file.path);
這是一個(gè)bool類(lèi)型的值,true表示是文件徒坡,false就是文件夾啦撕氧。
在后面的顯示上就可以通過(guò)這個(gè)來(lái)區(qū)分了。
還有一些頁(yè)面顯示美化的代碼就不貼了喇完,后面有項(xiàng)目地址可以自己下載下來(lái)看看伦泥。

打開(kāi)文件

文件管理器,看到的文件應(yīng)該要能打開(kāi)吧锦溪。下面就是判斷點(diǎn)擊的是文件時(shí)不脯,要彈出提示用什么應(yīng)用去打開(kāi),要寫(xiě)一點(diǎn)原生刻诊,不過(guò)也不難防楷。
自己寫(xiě)一個(gè)通道的方法,去調(diào)用
file_manager.dart

MethodChannel _channel = MethodChannel('openFileChannel');

openFile(String path) {
    final Map<String, dynamic> args = <String, dynamic>{'path': path};
    _channel.invokeMethod('openFile', args);
  }

然后在MainActivity.java文件中定義

private static Context mContext = null;
private static final String METHOD_CHANNEL = "openFileChannel";

"openFileChannel"名字要對(duì)應(yīng)一致
然后在onCreate方法中增加以下代碼

new MethodChannel(getFlutterView(), METHOD_CHANNEL).setMethodCallHandler(
                new MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
                        if (methodCall.method.equals("openFile")) {
                            String path = methodCall.argument("path");
                            openFile(mContext, path);
                            result.success("");
                        } else {
                            result.notImplemented();
                        }
                    }
                }
        );

方法名為openFile则涯,其實(shí)只有一個(gè)方法好像不用指定也是可以的复局,不過(guò)為了規(guī)范一點(diǎn),還是寫(xiě)上比較好是整。
dart那邊傳給Java層的是一個(gè)文件的路徑肖揣,然后調(diào)用openFile()方法,方法實(shí)現(xiàn)如下

private void openFile(Context context, String path) {
        try {
            if (!path.contains("file://")) {
                path = "file://" + path;
            }
            //獲取文件類(lèi)型
            String[] nameType = path.split("\\.");
            String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(nameType[1]);

            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setAction(Intent.ACTION_VIEW);
            //設(shè)置文件的路徑和文件類(lèi)型
            intent.setDataAndType(Uri.parse(path), mimeType);
            //跳轉(zhuǎn)
            context.startActivity(intent);
        } catch (Exception e) {
            System.out.println(e);
        }
    }

使用Intent的方式去打開(kāi)浮入,這里還是加上try...catch...吧龙优,因?yàn)橛行┪募?lèi)型好像會(huì)報(bào)錯(cuò),具體原因還沒(méi)去深究事秀,應(yīng)該是一些系統(tǒng)文件(有些連文件后綴都沒(méi)...)
整個(gè)文件管理器的實(shí)現(xiàn)主要方法就到這里了
實(shí)現(xiàn)的界面如下


界面

項(xiàng)目的代碼已經(jīng)上傳到我的GitHub彤断,如果覺(jué)得對(duì)你有幫助歡迎star,同時(shí)也會(huì)繼續(xù)更新完善

flutter版的文件管理器項(xiàng)目地址

其他

flutter入門(mén)widget的使用易迹。帶你認(rèn)識(shí)flutter widgets宰衙。根據(jù)flutter中文網(wǎng)widgets目錄進(jìn)行編寫(xiě)的一個(gè)庫(kù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末睹欲,一起剝皮案震驚了整個(gè)濱河市供炼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窘疮,老刑警劉巖袋哼,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異闸衫,居然都是意外死亡涛贯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)蔚出,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弟翘,“玉大人虫腋,你說(shuō)我怎么就攤上這事∠∮啵” “怎么了悦冀?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)滚躯。 經(jīng)常有香客問(wèn)我雏门,道長(zhǎng),這世上最難降的妖魔是什么掸掏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任茁影,我火速辦了婚禮,結(jié)果婚禮上丧凤,老公的妹妹穿的比我還像新娘募闲。我一直安慰自己,他們只是感情好愿待,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布浩螺。 她就那樣靜靜地躺著,像睡著了一般仍侥。 火紅的嫁衣襯著肌膚如雪要出。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天农渊,我揣著相機(jī)與錄音患蹂,去河邊找鬼。 笑死砸紊,一個(gè)胖子當(dāng)著我的面吹牛传于,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播醉顽,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼沼溜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了游添?” 一聲冷哼從身側(cè)響起系草,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎唆涝,沒(méi)想到半個(gè)月后悄但,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡石抡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了助泽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啰扛。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嚎京,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出隐解,到底是詐尸還是另有隱情鞍帝,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布煞茫,位于F島的核電站帕涌,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏续徽。R本人自食惡果不足惜蚓曼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钦扭。 院中可真熱鬧纫版,春花似錦、人聲如沸客情。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膀斋。三九已至梭伐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間仰担,已是汗流浹背糊识。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惰匙,地道東北人技掏。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像项鬼,于是被迫代替她去往敵國(guó)和親哑梳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容